home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Development Platforms / LISP Related / LISP Goodies / Wood / btrees.lisp < prev    next >
Encoding:
Text File  |  1992-09-02  |  122.4 KB  |  2,288 lines  |  [TEXT/CCL2]

  1. ;;;-*- Mode: Lisp; Package: WOOD -*-
  2.  
  3. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  4. ;;;
  5. ;;; btrees.lisp
  6. ;;; B* trees with variable length keys for pheaps.
  7. ;;;
  8. ;;; Copyright © 1992 Apple Computer, Inc. All rights reserved.
  9. ;;; Permission is given to use, copy, and modify this software provided
  10. ;;; that this copyright notice is attached to all derivative works.
  11. ;;; This software is provided "as is". Apple makes no warranty or
  12. ;;; representation, either express or implied, with respect to this software,
  13. ;;; its quality, accuracy, merchantability, or fitness for a particular
  14. ;;; purpose.
  15. ;;;
  16.  
  17. ;;; Key size is limited to 127 bytes with longer keys
  18. ;;; being stored as strings (and requiring an extra disk access).
  19. ;;; (longer strings are not yet implemented).
  20.  
  21. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  22. ;;;
  23. ;;; Modification History
  24. ;;;
  25. ;;; -------------- 0.5
  26. ;;; 07/28/92 bill  make p-map-btree deal correctly with insertion or
  27. ;;;                deletion while mapping.
  28. ;;; 07/27/92 bill  p-clear-btree, p-map-btree
  29. ;;; 06/30/92 bill  little bug in %split-btree-root
  30. ;;; 06/26/92 bill  btree vector indices defs -> woodequ
  31. ;;; 06/23/92 bill  Don't ignore type in p-make-btree
  32. ;;; -------------- 0.1
  33. ;;;
  34.  
  35. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  36. ;;;
  37. ;;; To do:
  38. ;;;
  39. ;;; 1) Maybe.
  40. ;;;    Replace the $btree_parent slot with $btree_mod-count for locking use.
  41. ;;;    Updating parents at shift or split time is too expensive.
  42. ;;;    Instead, pass around an ancestors list (stack-consed).
  43. ;;;
  44. ;;; 2) Implement keys longer than 127 bytes.
  45.  
  46. (in-package :wood)
  47.  
  48. (export '(p-make-btree p-btree-lookup p-btree-store p-btree-delete
  49.           dc-make-btree dc-btree-lookup dc-btree-store dc-btree-delete))
  50.  
  51. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  52. ;;;
  53. ;;; Node layout - subtype $v_btree-node
  54. ;;;
  55. ;;;  -------------------
  56. ;;; | $vector-header    |
  57. ;;; | subtype length    |
  58. ;;; |-------------------|
  59. ;;; | link              |
  60. ;;; | parent            |
  61. ;;; | used free         |
  62. ;;; | count flags       |
  63. ;;; | pointer[0]        |
  64. ;;; | len[1] key[1] ... |
  65. ;;; | pointer[1]        |
  66. ;;; | len[2] key[2] ... |
  67. ;;; |        ...        |
  68. ;;; | len[m] key[m] ... |
  69. ;;; | pointer[m]        |
  70. ;;;  -------------------
  71.  
  72. ;;; $vector-header is the standard vector header marker
  73. ;;; subtype is one byte, it's value is $v_btree-node
  74. ;;; length is the total length of the data portion of the block in bytes
  75. ;;; link is used by the GC so that it can walk btree nodes last.
  76. ;;; parent points at the parent node of this one, or at the btree
  77. ;;;   uvector for the root.
  78. ;;; used is 16 bits: the number of bytes that are in use at $btree_data
  79. ;;; free is 16 bits: the number of free bytes at the end of the block.
  80. ;;; count is 16 bits: the number of entries in this node
  81. ;;; flags is 16 bits of flags.
  82. ;;;   Bit 0 is set for a leaf page.
  83. ;;;   Bit 1 is set for the root page.
  84. ;;; pointer[i] is 4 bytes aligned on a 4-byte boundary.
  85. ;;;   For a non-leaf node, it points at another node in the tree
  86. ;;;   For a leaf node, it points at the indexed data.
  87. ;;;   pointer[m] for a leaf node points to the next leaf node.
  88. ;;; len[i] is a bytes giving the length of key[i]
  89. ;;;   if len[i] is 255, then there are three unused bytes followed
  90. ;;;   by a four byte pointer to a string containing the key.
  91. ;;;   otherwise, len[i] will always be < 128
  92. ;;;   (keys longer than 127 bytes are not yet implemented)
  93. ;;; key[i] is len[i] bytes of characters for the key followed
  94. ;;;   by enough padding bytes to get to the next 4-byte boundary.
  95.  
  96. (defconstant $btree_link $v_data)
  97. (defconstant $btree_parent (+ $btree_link 4))
  98. (defconstant $btree_used (+ $btree_parent 4))
  99. (defconstant $btree_free (+ $btree_used 2))
  100. (defconstant $btree_count (+ $btree_free 2))
  101. (defconstant $btree_flags (+ $btree_count 2))
  102. (defconstant $btree_data (+ $btree_flags 2))
  103.  
  104. (defconstant $btree_flags.leaf-bit 0)
  105. (defconstant $btree_flags.root-bit 1)
  106.  
  107. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  108. ;;;
  109. ;;; The documented interface
  110. ;;;
  111.  
  112. (defun p-make-btree (pheap &key area type)
  113.   (pptr pheap
  114.         (dc-make-btree (pheap-disk-cache pheap)
  115.                        (and area (pheap-pptr-pointer area pheap))
  116.                        (and type (require-type type 'fixnum)))))
  117.  
  118. (defun p-btree-lookup (btree key-string &optional default)
  119.   (let ((pheap (pptr-pheap btree)))
  120.     (multiple-value-bind (pointer immediate? found?)
  121.                          (dc-btree-lookup
  122.                           (pheap-disk-cache pheap)
  123.                           (pptr-pointer btree)
  124.                           (if (stringp key-string)
  125.                             key-string
  126.                             (p-load key-string)))
  127.       (if found?
  128.         (values
  129.          (if immediate?
  130.            pointer
  131.            (pptr pheap pointer))
  132.          t)
  133.         default))))
  134.  
  135. (defun p-btree-store (btree key-string default &optional (value default))
  136.   (let ((pheap (pptr-pheap btree)))
  137.     (multiple-value-bind (pointer immediate?)
  138.                          (%p-store pheap value)
  139.     (dc-btree-store
  140.      (pheap-disk-cache pheap)
  141.      (pptr-pointer btree)
  142.      (if (stringp key-string)
  143.        key-string
  144.        (p-load key-string))
  145.      pointer
  146.      immediate?)
  147.     (if immediate?
  148.       pointer
  149.       (pptr pheap pointer)))))
  150.  
  151. (defsetf p-btree-lookup p-btree-store)
  152.  
  153. (defun p-btree-delete (btree key-string)
  154.   (dc-btree-delete
  155.    (pptr-disk-cache btree)
  156.    (pptr-pointer btree)
  157.    (if (stringp key-string)
  158.      key-string
  159.      (p-load key-string))))
  160.  
  161. (defun p-clear-btree (btree)
  162.   (dc-clear-btree (pptr-disk-cache btree)
  163.                   (pptr-pointer btree))
  164.   btree)
  165.  
  166. (defun p-map-btree (btree function &optional from to)
  167.   (let* ((pheap (pptr-pheap btree))
  168.          (f #'(lambda (disk-cache key value imm?)
  169.                 (declare (ignore disk-cache))
  170.                 (funcall function key (if imm? value (pptr pheap value))))))
  171.     (declare (dynamic-extent f))
  172.     (dc-map-btree (pheap-disk-cache pheap)
  173.                   (pptr-pointer btree)
  174.                   f
  175.                   (if (or (null from) (stringp from))
  176.                     from
  177.                     (p-load from))
  178.                   (if (or (null to) (stringp to))
  179.                     to
  180.                     (p-load to)))))
  181.  
  182. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  183. ;;;
  184. ;;; disk-cache versions of the documented interface
  185. ;;;
  186.  
  187. (defun dc-make-btree (disk-cache &optional area type)
  188.   (let* ((btree (dc-make-uvector disk-cache $btree-size $v_btree area 0 t))
  189.          (root (dc-cons-btree-node
  190.                  disk-cache btree btree
  191.                  (logior (ash 1 $btree_flags.leaf-bit) (ash 1 $btree_flags.root-bit)))))
  192.     (accessing-disk-cache (disk-cache)
  193.       (svset.p btree $btree.root root)
  194.       (svset.p btree $btree.first-leaf root)
  195.       (when type
  196.         (svset.p btree $btree.type (require-type type 'fixnum) t)))
  197.     btree))
  198.  
  199. (defun dc-btree-lookup (disk-cache btree key-string)
  200.   (multiple-value-bind (node offset eq)
  201.                        (btree-find-leaf-node disk-cache btree key-string)
  202.     (when eq
  203.       (multiple-value-bind (pointer immediate?)
  204.                            (read-pointer disk-cache (+ node offset))
  205.         (values pointer immediate? t)))))
  206.  
  207. (defun dc-btree-store (disk-cache btree key-string value &optional
  208.                                        value-imm?)
  209.   (if (> (length key-string) 127)
  210.     (error "Keys longer than 127 bytes not supported yet."))
  211.   (multiple-value-bind (node offset eq)
  212.                        (btree-find-leaf-node disk-cache btree key-string)
  213.     (if eq
  214.       (setf (read-pointer disk-cache (+ node offset) value-imm?)
  215.             value)
  216.       (progn
  217.         (%btree-insert-in-leaf-node
  218.          disk-cache btree node offset key-string value value-imm?)
  219.         (accessing-disk-cache (disk-cache)
  220.           (svset.p btree $btree.count (1+ (svref.p btree $btree.count)) t))
  221.         (values value value-imm?)))))
  222.  
  223. (defun dc-btree-delete (disk-cache btree key-string)
  224.   (if (> (length key-string) 127)
  225.     (error "Keys longer than 127 bytes not supported yet."))
  226.   (multiple-value-bind (node offset eq)
  227.                        (btree-find-leaf-node disk-cache btree key-string)
  228.     (when eq
  229.       (%btree-delete-from-node disk-cache btree node offset t)
  230.       (accessing-disk-cache (disk-cache)
  231.         (svset.p btree $btree.count (1- (svref.p btree $btree.count)) t))
  232.       t)))
  233.  
  234. (defun dc-clear-btree (disk-cache btree)
  235.   (require-satisfies dc-vector-subtype-p disk-cache btree $v_btree)
  236.   (let* ((root-node (dc-%svref disk-cache btree $btree.root))
  237.          (first-leaf (dc-%svref disk-cache btree $btree.first-leaf)))
  238.     (accessing-disk-cache (disk-cache first-leaf)
  239.       (multiple-value-bind (node used free) (init-btree-node disk-cache first-leaf)
  240.         (declare (ignore node))
  241.         (fill.b (+ $btree_data used) 0 free))
  242.       (store.l btree $btree_parent)
  243.       (store.w (logior (ash 1 $btree_flags.root-bit)
  244.                        (ash 1 $btree_flags.leaf-bit)
  245.                        (load.w $btree_flags))
  246.                $btree_flags))
  247.     (dc-%svfill disk-cache btree
  248.       $btree.root first-leaf
  249.       ($btree.count t) 0
  250.       ($btree.count t) 0
  251.       ($btree.nodes t) 1)
  252.     (dc-%clear-node disk-cache root-node first-leaf))
  253.   btree)
  254.  
  255. (defun dc-%clear-node (disk-cache node first-leaf)
  256.   (require-satisfies dc-vector-subtype-p disk-cache node $v_btree-node)
  257.   (unless (eql node first-leaf)
  258.     (with-locked-page (disk-cache node nil buf offset)
  259.       (accessing-byte-array (buf offset)
  260.         (unless (logbitp $btree_flags.leaf-bit (load.w $btree_flags))
  261.           (let ((p $btree_data))
  262.             (declare (fixnum p))
  263.             (dotimes (i (load.w $btree_count))
  264.               (dc-%clear-node disk-cache (load.l p) first-leaf)
  265.               (incf p 4)
  266.               (incf p (normalize-size (1+ (load.b p)) 4)))
  267.             (dc-%clear-node disk-cache (load.l p) first-leaf)))
  268.         (dc-free-btree-node disk-cache nil node)))))
  269.  
  270. (defun dc-map-btree (disk-cache btree function &optional from to)
  271.   (unless (or (null from) (stringp from))
  272.     (setq from (require-type from '(or null string))))
  273.   (unless (or (null to) (stringp to))
  274.     (setq to (require-type to '(or null string))))
  275.   (multiple-value-bind (node p)
  276.                        (if from
  277.                          (btree-find-leaf-node disk-cache btree from)
  278.                          (values (dc-%svref disk-cache btree $btree.first-leaf)
  279.                                  $btree_data))
  280.     (declare (fixnum p))
  281.     (loop
  282.       (block once-per-node
  283.         (with-locked-page (disk-cache node nil buf buf-offset)
  284.           (accessing-byte-array (buf buf-offset)
  285.             (let ((max-p (+ $btree_data (load.w $btree_used) -4)))
  286.               (declare (fixnum max-p))
  287.               (loop
  288.                 (when (>= p max-p)
  289.                   (when (> p max-p)
  290.                     (error "Inconsistency: pointer off end of btree node"))
  291.                   (return))
  292.                 (multiple-value-bind (value imm?) (load.p p)
  293.                   (let* ((len (load.b (incf p 4)))
  294.                          (key (make-string len)))
  295.                     (declare (fixnum len)
  296.                              (dynamic-extent key))
  297.                     (load.string (the fixnum (1+ p)) len key)
  298.                     (when (and to (string< to key))
  299.                       (return-from dc-map-btree nil))
  300.                     (funcall function disk-cache key value imm?)
  301.                     (let ((newlen (load.b p)))
  302.                       (declare (fixnum newlen))
  303.                       (unless (and (eql newlen len)
  304.                                    (let ((new-key (make-string newlen)))
  305.                                      (declare (dynamic-extent new-key))
  306.                                      (load.string (the fixnum (1+ p)) newlen new-key)
  307.                                      (string= key new-key)))
  308.                         ; The user inserted or deleted something that caused
  309.                         ; the key to move. Need to find it again.
  310.                         (let (eq)
  311.                           (multiple-value-setq (node p eq)
  312.                             (btree-find-leaf-node disk-cache btree key))
  313.                           (when eq
  314.                             (incf p (normalize-size (1+ len) 4)))
  315.                           (return-from once-per-node))))
  316.                     (incf p (normalize-size (1+ len) 4))))))
  317.             (setq node (load.l p)
  318.                   p $btree_data)
  319.             (when (eql node $pheap-nil)
  320.               (return nil))))))))
  321.  
  322. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  323. ;;;
  324. ;;; Grungy internal details
  325. ;;; First, some generally useful utility functions
  326. ;;; 
  327.  
  328. (defun dc-cons-btree-node (disk-cache btree parent flags)
  329.   (let ((node (or (with-locked-page (disk-cache (+ $root-vector $v_data
  330.                                                    (* 4 $pheap.btree-free-list)))
  331.                     (accessing-disk-cache (disk-cache)
  332.                       (let ((free-list (svref.p $root-vector $pheap.btree-free-list)))
  333.                         (unless (eql $pheap-nil free-list)
  334.                           (svset.p $root-vector $pheap.btree-free-list
  335.                                    (accessing-disk-cache (disk-cache free-list)
  336.                                      (load.l $btree_parent)))
  337.                           free-list))))
  338.                   (init-btree-node
  339.                    disk-cache
  340.                    (%dc-allocate-new-memory disk-cache 1 $v_btree-node 0 t)))))
  341.     (accessing-disk-cache (disk-cache node)
  342.       (store.l parent $btree_parent)
  343.       (store.w flags $btree_flags))
  344.     (with-locked-page (disk-cache (+ btree $v_data (* 4 $btree.nodes)) t)
  345.       (accessing-disk-cache (disk-cache)
  346.         (svset.p btree $btree.nodes (1+ (svref.p btree $btree.nodes)) t)))
  347.     node))
  348.  
  349. (defun dc-free-btree-node (disk-cache btree node)
  350.   (multiple-value-bind (node used free) (init-btree-node disk-cache node)
  351.     (accessing-disk-cache (disk-cache node)
  352.       (fill.b (+ $btree_data used) 0 free)))
  353.   (with-locked-page (disk-cache $root-vector t)
  354.     (accessing-disk-cache (disk-cache)
  355.       (let ((free-list (svref.p $root-vector $pheap.btree-free-list)))
  356.         (accessing-disk-cache (disk-cache node)
  357.           (store.l free-list $btree_parent)))
  358.       (svset.p $root-vector $pheap.btree-free-list node)))
  359.   (when btree
  360.     (with-locked-page (disk-cache (+ btree $v_data (* 4 $btree.nodes)) t)
  361.       (accessing-disk-cache (disk-cache)
  362.         (svset.p btree $btree.nodes (1- (svref.p btree $btree.nodes)) t)))))
  363.  
  364. (defun init-btree-node (disk-cache node)
  365.   (accessing-disk-cache (disk-cache node)
  366.     (let* ((vector-size (%vector-size.p node))
  367.            (data-size (- vector-size (- $btree_data $v_data)))
  368.            (used 4)
  369.            (free (- data-size used)))
  370.       (store.l $pheap-nil $btree_link)
  371.       (store.w used $btree_used)
  372.       (store.w free $btree_free)
  373.       (store.w 0 $btree_count)
  374.       (store.l $pheap-nil $btree_data)
  375.       (values node used free))))
  376.  
  377. (defun %btree-leaf-node-p (disk-cache node)
  378.   (accessing-disk-cache (disk-cache node)
  379.     (logbitp $btree_flags.leaf-bit (load.w $btree_flags))))
  380.  
  381. (defun %btree-root-node-p (disk-cache node)
  382.   (accessing-disk-cache (disk-cache node)
  383.     (logbitp $btree_flags.root-bit (load.w $btree_flags))))
  384.  
  385. ; Returns two values:
  386. ; 1) offset - from node for the place where key-string goes
  387. ; 2) eq     - True if the key at this offset is key-string
  388. (defun btree-find-leaf-node (disk-cache btree key-string)
  389.   (require-satisfies dc-vector-subtype-p disk-cache btree $v_btree)
  390.   (let ((node (dc-%svref disk-cache btree $btree.root)))
  391.     (loop
  392.       (multiple-value-bind (offset eq)
  393.                            (%btree-search-node disk-cache node key-string)
  394.         (when (%btree-leaf-node-p disk-cache node)
  395.           (return (values node offset eq)))
  396.         (setq node (read-long disk-cache (+ node offset)))
  397.         (require-satisfies dc-vector-subtype-p
  398.                            disk-cache node $v_btree-node)))))
  399.  
  400. ; This one calls the disk-cache code directly and accesses the
  401. ; page vector itself so that it can be reasonably fast.
  402. ; Returns same two values as btree-find-leaf-node
  403. ; plus a third value which is the offset to the node just to the left of the found one.
  404. (defun %btree-search-node (disk-cache node key-string)
  405.   (with-locked-page (disk-cache node nil vec offset bytes)
  406.     (declare (fixnum offset bytes))
  407.     (accessing-byte-array (vec offset)
  408.       (let* ((end (+ offset $btree_data (load.uw $btree_used)))
  409.              (ptr (+ offset $btree_data 4))
  410.              (last-ptr nil))
  411.         (declare (fixnum end ptr))
  412.         (declare (fixnum offset bytes))
  413.         (unless (>= (the fixnum (+ offset bytes)) end)
  414.           (error "End of btree node is past end of disk page"))
  415.         (loop
  416.           (if (>= ptr end)
  417.             (return (values (- ptr offset 4)
  418.                             nil
  419.                             (if last-ptr (- last-ptr offset 4)))))
  420.           (let* ((len (aref vec ptr))
  421.                  (str (make-string len)))
  422.             (declare (dynamic-extent str))
  423.             (%copy-byte-array-portion vec (the fixnum (1+ ptr)) len str 0)
  424.             ; Here's where we'll eventually use part of the
  425.             ; $btree_flags to select a sorting predicate.
  426.             (let ((compare (compare-strings key-string str)))
  427.               (declare (fixnum compare))
  428.               (when (<= compare 0)
  429.                      (return (values (- ptr offset 4) 
  430.                                      (eql compare 0)
  431.                                      (if last-ptr (- last-ptr offset 4))))))
  432.             (setq last-ptr ptr)
  433.             (incf ptr (normalize-size (+ 5 len) 4))))))))
  434.  
  435. (defun compare-strings (str1 str2)
  436.   (cond ((string< str1 str2) -1)
  437.         ((string= str1 str2) 0)
  438.         (t 1)))
  439.  
  440. ; Search a node for a pointer to a subnode.
  441. ; Return two values, the offset for the subnode, and the offset
  442. ; for the subnode just before it.
  443. (defun %btree-search-for-subnode (disk-cache node subnode)
  444.   (with-locked-page (disk-cache node nil vec offset bytes)
  445.     (declare (fixnum offset bytes))
  446.     (accessing-byte-array (vec offset)
  447.       (let* ((end (+ offset $btree_data (load.uw $btree_used)))
  448.              (ptr (+ offset $btree_data))
  449.              (last-ptr nil))
  450.         (declare (fixnum end ptr))
  451.         (declare (fixnum offset bytes))
  452.         (unless (>= (the fixnum (+ offset bytes)) end)
  453.           (error "End of btree node is past end of disk page"))
  454.         (accessing-byte-array (vec)
  455.           (loop
  456.             (when (eql subnode (load.p ptr))
  457.               (return (values (- ptr offset) 
  458.                               (if last-ptr (- last-ptr offset)))))
  459.             (setq last-ptr ptr)
  460.             (incf ptr 4)
  461.             (if (>= ptr end)
  462.               (return nil))
  463.             (incf ptr (normalize-size (1+ (load.b ptr)) 4))))))))
  464.  
  465. ; Fill the SIZES array with the sizes of the entries in NODE.
  466. ; If one of the entries is at INSERT-OFFSET, put INSERT-SIZE
  467. ; into SIZES at that index, and return the index.
  468. ; Otherwise, return NIL.
  469. (defun %lookup-node-sizes (disk-cache node sizes count &optional insert-offset insert-size
  470.                                       (start 0))
  471.   (accessing-disk-cache (disk-cache node)
  472.     (unless count
  473.       (setq count (load.uw $btree_count)))
  474.     (when insert-offset (incf count))
  475.     (let ((p (+ $btree_data 4))
  476.           (p-at-offset (and insert-offset (+ insert-offset 4)))
  477.           insert-index
  478.           (index (require-type start 'fixnum)))
  479.       (declare (fixnum p))
  480.       (dotimes (i count)
  481.         (if (eql p p-at-offset)
  482.           (setf (aref sizes index) insert-size
  483.                 insert-index index
  484.                 p-at-offset nil)
  485.           (incf p (setf (aref sizes index) (normalize-size (+ 5 (load.b p)) 4))))
  486.         (incf index))
  487.       (when (and insert-offset (null insert-index))
  488.         (error "Inconsistency: didn't find insert-offset"))
  489.       (unless (eql p (+ $btree_data (load.uw $btree_used)))
  490.         (error "Inconsistency: walking node's entries didn't end up at end"))
  491.       insert-index)))
  492.  
  493. ; When we move entries around in a non-leaf nodes, the parent pointers
  494. ; need to be updated.
  495. ; This will go away if I eliminate the parent pointers and replace
  496. ; them with passing around the ancestor list.
  497. ; Doing this will make insertion and deletion slightly faster
  498. ; at the expense of making it hard to click around in a btree
  499. ; in the inspector.
  500. (defun %btree-update-childrens-parents (disk-cache node &optional start-ptr end-ptr)
  501.   (with-locked-page (disk-cache node nil node-buf node-buf-offset)
  502.     (accessing-byte-array (node-buf)
  503.       (let* ((used (load.uw (+ node-buf-offset $btree_used)))
  504.              (p (or start-ptr (+ node-buf-offset $btree_data)))
  505.              (max-p (or end-ptr (+ node-buf-offset $btree_data used)))
  506.              child)
  507.         (declare (fixnum p max-p))
  508.         (loop
  509.           (setq child (load.p p))
  510.           (require-satisfies dc-vector-subtype-p disk-cache child $v_btree-node)
  511.           (accessing-disk-cache (disk-cache child)
  512.             (store.p node $btree_parent))
  513.           (incf p 4)
  514.           (when (>= p max-p)
  515.             (unless (eql p max-p)
  516.               (error "Inconsistency. Node scan went past expected end."))
  517.             (return))
  518.           (incf p (normalize-size (+ 1 (load.b p)) 4)))))))
  519.  
  520. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  521. ;;
  522. ;; Here's where the guts of an insert happens.
  523. ;; We know that the key-string belongs at offset from node.
  524. ;; Insert it there if it fits.
  525. ;; Otherwise do the btree stuff:
  526. ;;   Try to shuffle things between this node and its left or right
  527. ;;     neighbor (shuffle right not implemented yet).
  528. ;;   If that doesn't work, split this node and its left (right) neighbor
  529. ;;     into three nodes.
  530.  
  531. (defun %btree-insert-in-leaf-node (disk-cache btree node offset key-string value
  532.                                               &optional value-imm? (key-length (length key-string)))
  533.   (accessing-disk-cache (disk-cache node)
  534.     (let* ((free (load.uw $btree_free))
  535.            (used (load.uw $btree_used))
  536.            (size (normalize-size (+ 5 key-length) 4)))
  537.       (declare (fixnum free used size))
  538.       (if (> key-length 127)
  539.         (error "Keys longer than 127 not supported yet."))
  540.       (when (<= size free)
  541.         ; Will fit in this node
  542.         (with-locked-page (disk-cache node t node-buf node-buf-offset nil node-page)
  543.           (let* ((bytes-to-move (- used (- offset $btree_data)))
  544.                  (p (+ node-buf-offset offset)))
  545.             (declare (fixnum bytes-to-move p))
  546.             (%copy-byte-array-portion node-buf p bytes-to-move
  547.                                       node-buf (+ p size) node-page)
  548.             (%store-btree-entry
  549.              node-buf p node-page
  550.              key-string key-length value value-imm? size)
  551.             (accessing-byte-array (node-buf node-buf-offset node-page)
  552.               (store.w (1+ (load.uw $btree_count)) $btree_count)
  553.               (store.w (+ used size) $btree_used)
  554.               (store.w (- free size) $btree_free))))
  555.         (return-from %btree-insert-in-leaf-node nil))
  556.       ; Won't fit. Try to shuffle entries to neighbors
  557.       (let* ((parent (load.l $btree_parent))
  558.              (flags (load.w $btree_flags))
  559.              (root-p (logbitp $btree_flags.root-bit flags))
  560.              (count (load.uw $btree_count))
  561.              (sizes (make-array (the fixnum (1+ count))))
  562.              (node-index nil)         ; The index of this node in sizes
  563.              right-offset parent-used
  564.              left-offset left-neighbor
  565.              (left-used 0)
  566.              (left-free 0)
  567.              (left-entry-size 0)
  568.              (right-entry-size 0)
  569.              right-neighbor right-used right-free)
  570.         (declare (fixnum flags count left-used left-free left-entry-size right-entry-size)
  571.                  (dynamic-extent sizes))
  572.         ; Fill in sizes array
  573.         (setq node-index (%lookup-node-sizes disk-cache node sizes count offset size))
  574.         (unless root-p
  575.           ; Try to shuffle to left neighbor
  576.           (accessing-disk-cache (disk-cache parent)
  577.             (multiple-value-setq (right-offset left-offset)
  578.               (%btree-search-for-subnode disk-cache parent node))
  579.             (setq parent-used (load.uw $btree_used))
  580.             (when left-offset
  581.               (setq left-entry-size (normalize-size (+ 5 (load.b (+ left-offset 4))) 4)
  582.                     left-neighbor (load.l left-offset))
  583.               (when left-neighbor
  584. ;                (break "Trying to shuffle left")
  585.                 (require-satisfies dc-vector-subtype-p 
  586.                                    disk-cache left-neighbor $v_btree-node)
  587.                 (accessing-disk-cache (disk-cache left-neighbor) 
  588.                   (setq left-free (load.uw $btree_free)
  589.                         left-used (load.uw $btree_used)))
  590.                 (let* ((bytes-added 0)
  591.                        (node-free free)
  592.                        (left-still-free left-free)
  593.                        (move-left-size 0)
  594.                        (current-size 0)
  595.                        (temp-string (make-string 128))
  596.                        insert-string insert-length)
  597.                   (declare (fixnum bytes-added node-free left-still-free move-left-size current-size))
  598.                   (declare (dynamic-extent temp-string))
  599.                   (dotimes (i count)
  600.                     (setq current-size (aref sizes i)
  601.                           move-left-size current-size)
  602.                     (unless (<= 0 (decf left-still-free move-left-size))
  603.                       (return))
  604.                     (incf bytes-added move-left-size)
  605.                     (when (or (eql i node-index)
  606.                               (>= (incf node-free current-size) size))
  607.                       ; Can shift to the left neighbor
  608. ;                      (break "Shuffling left")
  609.                       (with-locked-page (disk-cache parent t parent-buf parent-buf-offset nil parent-page)
  610.                         (with-locked-page (disk-cache left-neighbor t left-buf left-buf-offset nil left-page)
  611.                           (with-locked-page (disk-cache node t node-buf node-buf-offset nil node-page)
  612.                             (let* ((p (+ left-buf-offset $btree_data left-used))
  613.                                    (bytes-to-move bytes-added))
  614.                               (declare (fixnum p bytes-to-move))
  615.                               ; Move link to new end of left-neighbor
  616.                               (%copy-byte-array-portion
  617.                                left-buf (decf p 4) 4 left-buf (+ p bytes-added) left-page)
  618.                               ; Move entries from node to left-neighbor
  619.                               (when (eql i node-index)
  620. ;                                (format t "~&(eql i node-index): %btree-insert-in-leaf-node")
  621.                                 (decf bytes-to-move size))
  622.                               (%copy-byte-array-portion
  623.                                node-buf (+ node-buf-offset $btree_data) bytes-to-move
  624.                                left-buf p left-page)
  625.                               (incf p bytes-to-move)
  626.                               (when (eql i node-index)
  627.                                 (%store-btree-entry
  628.                                  left-buf p left-page
  629.                                  key-string key-length value value-imm? size))
  630.                               ; update the used, free, & count fields for left-neighbor
  631.                               (accessing-byte-array (left-buf left-buf-offset left-page)
  632.                                 (store.w (incf left-used bytes-added) $btree_used)
  633.                                 (store.w (- (load.w $btree_free) bytes-added) $btree_free)
  634.                                 (store.w (+ (load.w $btree_count) (1+ i)) $btree_count))
  635.                               ; Update the parent pointers for the sub-nodes we moved
  636.                               ; Left-neighbor is all set.
  637.                               ; fixup node
  638.                               ; bytes-to-move is number of bytes that moved from node to left-neighbor
  639.                               (if (eql i node-index)
  640.                                 ; new entry goes to parent and is already in left-neighbor
  641.                                 (progn
  642.                                   (decf used bytes-to-move)
  643.                                   (incf free bytes-to-move)
  644.                                   (%copy-byte-array-portion
  645.                                    node-buf (+ node-buf-offset $btree_data bytes-to-move) used
  646.                                    node-buf (+ node-buf-offset $btree_data) node-page)
  647.                                   (accessing-byte-array (node-buf node-buf-offset node-page)
  648.                                     (fill.b (+ $btree_data used) 0 bytes-to-move)
  649.                                     (store.w used $btree_used)
  650.                                     (store.w free $btree_free)
  651.                                     (store.w (- (load.uw $btree_count) i) $btree_count))
  652.                                   (setq insert-string key-string
  653.                                         insert-length key-length))
  654.                                 (progn
  655.                                   ; Store the new left-entry in insert-xxx
  656.                                   (accessing-byte-array (node-buf nil node-page)
  657.                                     (let ((p (+ node-buf-offset $btree_data bytes-to-move  (- 4 move-left-size))))
  658.                                       (setq insert-length (load.b p))
  659.                                       (load.string (incf p 1) insert-length (setq insert-string temp-string))))
  660.                                   ; Insert the new entry into node
  661.                                   (let* ((offset-from-data (- offset $btree_data))
  662.                                          (bytes-before-new (- offset-from-data bytes-to-move))
  663.                                          (bytes-after-new (- used offset-from-data)))
  664.                                     (declare (fixnum offset-from-data bytes-before-new bytes-after-new))
  665.                                     (%copy-byte-array-portion
  666.                                      node-buf (+ node-buf-offset $btree_data bytes-to-move) bytes-before-new
  667.                                      node-buf (+ node-buf-offset $btree_data) node-page)
  668.                                     (%copy-byte-array-portion
  669.                                      node-buf (+ node-buf-offset offset) bytes-after-new
  670.                                      node-buf (+ node-buf-offset $btree_data bytes-before-new size))
  671.                                     (let ((p (+ node-buf-offset $btree_data bytes-before-new)))
  672.                                       (%store-btree-entry
  673.                                        node-buf p node-page
  674.                                        key-string key-length value value-imm? size)
  675.                                       (incf p size)
  676.                                       (accessing-byte-array (node-buf nil node-page)
  677.                                         (let ((end-fill (- used (+ bytes-before-new size bytes-after-new))))
  678.                                           (declare (fixnum end-fill))
  679.                                           (when (> end-fill 0)
  680.                                             (fill.b (+ p bytes-after-new) 0 end-fill))
  681.                                           (accessing-byte-array (node-buf node-buf-offset node-page)
  682.                                             (store.w (- used end-fill) $btree_used)
  683.                                             (store.w (+ free end-fill) $btree_free)
  684.                                             (store.w (- count i) $btree_count)))))))))))
  685.                         ; Finally, insert the new left-entry in parent
  686.                         (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  687.                           (let* ((insert-size (normalize-size (+ 5 insert-length) 4))
  688.                                  (size-diff (- insert-size left-entry-size))
  689.                                  (parent-free (load.uw $btree_free))
  690.                                  (parent-used (load.uw $btree_used))
  691.                                  (bytes-after-left-entry (- parent-used left-entry-size (- left-offset $btree_data))))
  692.                             (declare (fixnum insert-size size-diff parent-free parent-used bytes-after-left-entry))
  693.                             (when (>= parent-free size-diff)
  694.                               ; The insert-string will fit in the parent
  695.                               (incf parent-used size-diff)
  696.                               (decf parent-free size-diff)
  697.                               (%copy-byte-array-portion
  698.                                parent-buf (+ parent-buf-offset left-offset left-entry-size) bytes-after-left-entry
  699.                                parent-buf (+ parent-buf-offset left-offset insert-size) parent-page)
  700.                               (when (< size-diff 0)
  701.                                 (fill.b (+ $btree_data parent-used) 0 (- size-diff)))
  702.                               (let ((p (+ parent-buf-offset left-offset 4))
  703.                                     (filler (- insert-size insert-length 5)))
  704.                                 (declare (fixnum p filler))
  705.                                 (accessing-byte-array (parent-buf nil parent-page)
  706.                                   (store.b insert-length p)
  707.                                   (incf p)
  708.                                   (%copy-byte-array-portion
  709.                                    insert-string 0 insert-length parent-buf p parent-page)
  710.                                   (when (> filler 0)
  711.                                     (incf p insert-length)
  712.                                     (fill.b p 0 filler))))
  713.                               (store.w parent-free $btree_free)
  714.                               (store.w parent-used $btree_used)
  715. ;                              (format t "~&Shuffled left.")
  716. ;                              (check-btree-consistency disk-cache btree)
  717.                               (return-from %btree-insert-in-leaf-node :left-shift))
  718.                             ; The insert string won't fit. We have to do a recursive call
  719.                             (%copy-byte-array-portion
  720.                              parent-buf (+ parent-buf-offset left-offset left-entry-size) bytes-after-left-entry
  721.                              parent-buf (+ parent-buf-offset left-offset) parent-page)
  722.                             (fill.b (+ left-offset bytes-after-left-entry) 0 left-entry-size)
  723.                             (store.w (- parent-used left-entry-size) $btree_used)
  724.                             (store.w (+ parent-free left-entry-size) $btree_free)
  725.                             (store.w (1- (load.uw $btree_count)) $btree_count)
  726.                             (%btree-insert-in-inner-node
  727.                              disk-cache btree parent left-offset insert-string left-neighbor
  728.                              nil insert-length)
  729. ;                            (format t "~&Shuffled left leaf node and inserted.")
  730. ;                            (check-btree-consistency disk-cache btree)
  731.                             (return-from %btree-insert-in-leaf-node :left-shift-and-insert)))))))))
  732.             ; Didn't fit in left neighbor. Try right neighbor
  733.             (accessing-disk-cache (disk-cache parent)
  734.               (when (< (+ right-offset 4) (+ $btree_data parent-used))
  735.                 (setq right-entry-size (normalize-size (+ 5 (load.b (+ right-offset 4))) 4)
  736.                       right-neighbor (load.l (+ right-offset right-entry-size)))))
  737.             (when (eql $pheap-nil right-neighbor) (setq right-neighbor nil))
  738.             (when right-neighbor
  739. ;              (format t "~&Trying to shuffle right")
  740.               (require-satisfies dc-vector-subtype-p 
  741.                                  disk-cache right-neighbor $v_btree-node)
  742.               (accessing-disk-cache (disk-cache right-neighbor) 
  743.                 (setq right-free (load.uw $btree_free)
  744.                       right-used (load.uw $btree_used)))
  745.               ; Almost a copy of the left-neighbor case above
  746.               ; Debug that code, then modify it to go here.
  747.               )))
  748.         ; Can't slide stuff around. Need to split two nodes into three
  749.         ; (or one node into two if it's the root)
  750.         (when root-p
  751.           ; We're passing a large amount of state.
  752.           ; Maybe it would be better to recompute some of this stuff.
  753.           (%btree-split-root
  754.            disk-cache btree node offset key-string key-length value value-imm?
  755.            size used free count flags sizes node-index)
  756.           (return-from %btree-insert-in-leaf-node :split-root))
  757.         ; again, there's an awfully large amount of state here.
  758.         (let ((normalized-offset (- offset $btree_data)))
  759.           (declare (fixnum normalized-offset))
  760.           (cond (left-neighbor
  761.                  (%btree-split-leaf-node
  762.                   disk-cache btree key-string key-length value value-imm?
  763.                   (the fixnum (+ normalized-offset left-used -4)) flags
  764.                   parent left-offset left-entry-size
  765.                   left-neighbor left-used left-free
  766.                   node used free))
  767.                 (right-neighbor
  768.                  (%btree-split-leaf-node
  769.                   disk-cache btree key-string key-length value value-imm?
  770.                   normalized-offset flags
  771.                   parent right-offset right-entry-size
  772.                   node used free
  773.                   right-neighbor right-used right-free))
  774.                 (t (error "Not root-p but no neighbors"))))
  775.         (return-from %btree-insert-in-leaf-node :split-node)))))
  776.  
  777. (defun %btree-insert-in-inner-node (disk-cache btree node offset key-string value value-imm? key-length)
  778.   (accessing-disk-cache (disk-cache node)
  779.     (let* ((free (load.uw $btree_free))
  780.            (used (load.uw $btree_used))
  781.            (size (normalize-size (+ 5 key-length) 4)))
  782.       (declare (fixnum free used size))
  783.       (if (> key-length 127)
  784.         (error "Keys longer than 127 not supported yet."))
  785.       (when (<= size free)
  786.         ; Will fit in this node
  787.         (with-locked-page (disk-cache node t node-buf node-buf-offset nil node-page)
  788.           (let* ((bytes-to-move (- used (- offset $btree_data)))
  789.                  (p (+ node-buf-offset offset)))
  790.             (declare (fixnum bytes-to-move p))
  791.             (%copy-byte-array-portion node-buf p bytes-to-move
  792.                                       node-buf (+ p size) node-page)
  793.             (%store-btree-entry
  794.              node-buf p node-page
  795.              key-string key-length value value-imm? size)
  796.             (accessing-byte-array (node-buf node-buf-offset node-page)
  797.               (store.w (1+ (load.uw $btree_count)) $btree_count)
  798.               (store.w (+ used size) $btree_used)
  799.               (store.w (- free size) $btree_free))))
  800.         (return-from %btree-insert-in-inner-node nil))
  801.       ; Won't fit. Try to shuffle entries to neighbors
  802.       (let* ((parent (load.l $btree_parent))
  803.              (flags (load.w $btree_flags))
  804.              (root-p (logbitp $btree_flags.root-bit flags))
  805.              (count (load.uw $btree_count))
  806.              (sizes (make-array (the fixnum (1+ count))))
  807.              (node-index nil)         ; The index of this node in sizes
  808.              right-offset parent-used
  809.              left-offset left-neighbor
  810.              (left-used 0)
  811.              (left-free 0)
  812.              (left-entry-size 0)
  813.              (right-entry-size 0)
  814.              right-neighbor right-used right-free)
  815.         (declare (fixnum flags count left-used left-free left-entry-size right-entry-size)
  816.                  (dynamic-extent sizes))
  817.         (require-satisfies dc-vector-subtype-p disk-cache value $v_btree-node)
  818.         ; Fill in sizes array
  819.         (setq node-index (%lookup-node-sizes disk-cache node sizes count offset size))
  820.         (unless root-p
  821.           ; Try to shuffle to left neighbor
  822.           (accessing-disk-cache (disk-cache parent)
  823.             (multiple-value-setq (right-offset left-offset)
  824.               (%btree-search-for-subnode disk-cache parent node))
  825.             (setq parent-used (load.uw $btree_used))
  826.             (when left-offset
  827.               (setq left-entry-size (normalize-size (+ 5 (load.b (+ left-offset 4))) 4)
  828.                     left-neighbor (load.l left-offset))
  829.               (when left-neighbor
  830. ;                (break "Trying to shuffle left")
  831.                 (require-satisfies dc-vector-subtype-p 
  832.                                    disk-cache left-neighbor $v_btree-node)
  833.                 (accessing-disk-cache (disk-cache left-neighbor) 
  834.                   (setq left-free (load.uw $btree_free)
  835.                         left-used (load.uw $btree_used)))
  836.                 (let* ((bytes-added 0)
  837.                        (node-free free)
  838.                        (left-entry-string-size (- left-entry-size 4))
  839.                        (left-still-free left-free)
  840.                        (last-size left-entry-size)
  841.                        (move-left-size 0)
  842.                        (current-size 0)
  843.                        (temp-string (make-string 128))
  844.                        insert-string insert-length)
  845.                   (declare (fixnum bytes-added node-free left-entry-string-size
  846.                                    left-still-free last-size move-left-size current-size))
  847.                   (declare (dynamic-extent temp-string))
  848.                   (dotimes (i count)
  849.                     (setq current-size (aref sizes i)
  850.                           move-left-size last-size
  851.                           last-size current-size)
  852.                     (unless (<= 0 (decf left-still-free move-left-size))
  853.                       (return))
  854.                     (incf bytes-added move-left-size)
  855.                     (when (or (eql i node-index)
  856.                               (>= (incf node-free current-size) size))
  857.                       ; Can shift to the left neighbor
  858. ;                      (break "Shuffling left inner node")
  859.                       (with-locked-page (disk-cache parent t parent-buf parent-buf-offset nil parent-page)
  860.                         (with-locked-page (disk-cache left-neighbor t left-buf left-buf-offset nil left-page)
  861.                           (with-locked-page (disk-cache node t node-buf node-buf-offset nil node-page)
  862.                             (let* ((p (+ left-buf-offset $btree_data left-used))
  863.                                    (child-update-pointer 0)
  864.                                    (bytes-to-move bytes-added))
  865.                               (declare (fixnum p child-update-pointer bytes-to-move))
  866.                               ; Copy key from parent into left neighbor
  867.                               (%copy-byte-array-portion
  868.                                parent-buf (+ parent-buf-offset left-offset 4)
  869.                                left-entry-string-size left-buf p left-page)
  870.                               (incf p left-entry-string-size)
  871.                               (setq child-update-pointer p)
  872.                               (decf bytes-to-move left-entry-string-size)
  873.                               ; Move entries from node to left-neighbor
  874.                               (when (eql i node-index)
  875. ;                                (format t "~&(eql i node-index): %btree-insert-in-inner-node")
  876.                                 (decf bytes-to-move 4))
  877.                               (%copy-byte-array-portion
  878.                                node-buf (+ node-buf-offset $btree_data) bytes-to-move
  879.                                left-buf p left-page)
  880.                               (incf p bytes-to-move)
  881.                               (when (eql i node-index)
  882.                                 (accessing-byte-array (left-buf nil left-page)
  883.                                   (store.p value p value-imm?)))
  884.                               ; update the used, free, & count fields for left-neighbor
  885.                               (accessing-byte-array (left-buf left-buf-offset left-page)
  886.                                 (store.w (incf left-used bytes-added) $btree_used)
  887.                                 (store.w (- (load.w $btree_free) bytes-added) $btree_free)
  888.                                 (store.w (+ (load.w $btree_count) (1+ i)) $btree_count))
  889.                               ; Update the parent pointers for the sub-nodes we moved
  890.                               (%btree-update-childrens-parents
  891.                                disk-cache left-neighbor child-update-pointer)
  892.                               ; Left-neighbor is all set.
  893.                               ; fixup node
  894.                               ; bytes-to-move is number of bytes that moved from node to left-neighbor
  895.                               (if (eql i node-index)
  896.                                 ; new entry goes to parent
  897.                                 (progn
  898.                                   (decf used bytes-to-move)
  899.                                   (incf free bytes-to-move)
  900.                                   (%copy-byte-array-portion
  901.                                    node-buf (+ node-buf-offset $btree_data bytes-to-move) used
  902.                                    node-buf (+ node-buf-offset $btree_data) node-page)
  903.                                   (accessing-byte-array (node-buf node-buf-offset node-page)
  904.                                     (fill.b (+ $btree_data used) 0 bytes-to-move)
  905.                                     (store.w used $btree_used)
  906.                                     (store.w free $btree_free)
  907.                                     (store.w (- (load.uw $btree_count) i) $btree_count))
  908.                                   (setq insert-string key-string
  909.                                         insert-length key-length))
  910.                                 (progn
  911.                                   ; Store the new left-entry in insert-xxx
  912.                                   (accessing-byte-array (node-buf nil node-page)
  913.                                     (let ((p (+ node-buf-offset $btree_data bytes-to-move)))
  914.                                       (setq insert-length (load.b p))
  915.                                       (load.string (incf p 1) insert-length (setq insert-string temp-string))))
  916.                                   ; Insert the new entry into node
  917.                                   (incf bytes-to-move (- current-size 4))
  918.                                   (let* ((offset-from-data (- offset $btree_data))
  919.                                          (bytes-before-new (- offset-from-data bytes-to-move))
  920.                                          (bytes-after-new (- used offset-from-data)))
  921.                                     (declare (fixnum offset-from-data bytes-before-new bytes-after-new))
  922.                                     (%copy-byte-array-portion
  923.                                      node-buf (+ node-buf-offset $btree_data bytes-to-move) bytes-before-new
  924.                                      node-buf (+ node-buf-offset $btree_data) node-page)
  925.                                     (%copy-byte-array-portion
  926.                                      node-buf (+ node-buf-offset offset) bytes-after-new
  927.                                      node-buf (+ node-buf-offset $btree_data bytes-before-new size))
  928.                                     (let ((p (+ node-buf-offset $btree_data bytes-before-new)))
  929.                                       (%store-btree-entry
  930.                                        node-buf p node-page
  931.                                        key-string key-length value value-imm? size)
  932.                                       (incf p size)
  933.                                       (accessing-byte-array (node-buf nil node-page)
  934.                                         (let ((end-fill (- used (+ bytes-before-new size bytes-after-new))))
  935.                                           (declare (fixnum end-fill))
  936.                                           (when (> end-fill 0)
  937.                                             (fill.b (+ p bytes-after-new) 0 end-fill))
  938.                                           (accessing-byte-array (node-buf node-buf-offset node-page)
  939.                                             (store.w (- used end-fill) $btree_used)
  940.                                             (store.w (+ free end-fill) $btree_free)
  941.                                             (store.w (- count i) $btree_count)))))))))))
  942.                         ; Finally, insert the new left-entry in parent
  943.                         (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  944.                           (let* ((insert-size (normalize-size (+ 5 insert-length) 4))
  945.                                  (size-diff (- insert-size left-entry-size))
  946.                                  (parent-free (load.uw $btree_free))
  947.                                  (parent-used (load.uw $btree_used))
  948.                                  (bytes-after-left-entry (- parent-used left-entry-size (- left-offset $btree_data))))
  949.                             (declare (fixnum insert-size size-diff parent-free parent-used bytes-after-left-entry))
  950.                             (when (>= parent-free size-diff)
  951.                               ; The insert-string will fit in the parent
  952.                               (incf parent-used size-diff)
  953.                               (decf parent-free size-diff)
  954.                               (%copy-byte-array-portion
  955.                                parent-buf (+ parent-buf-offset left-offset left-entry-size) bytes-after-left-entry
  956.                                parent-buf (+ parent-buf-offset left-offset insert-size) parent-page)
  957.                               (when (< size-diff 0)
  958.                                 (fill.b (+ $btree_data parent-used) 0 (- size-diff)))
  959.                               (let ((p (+ parent-buf-offset left-offset 4))
  960.                                     (filler (- insert-size insert-length 5)))
  961.                                 (declare (fixnum p filler))
  962.                                 (accessing-byte-array (parent-buf nil parent-page)
  963.                                   (store.b insert-length p)
  964.                                   (incf p)
  965.                                   (%copy-byte-array-portion
  966.                                    insert-string 0 insert-length parent-buf p parent-page)
  967.                                   (when (> filler 0)
  968.                                     (incf p insert-length)
  969.                                     (fill.b p 0 filler))))
  970.                               (store.w parent-free $btree_free)
  971.                               (store.w parent-used $btree_used)
  972. ;                              (format t "~&Shuffled left inner node.")
  973. ;                              (check-btree-consistency disk-cache btree)
  974.                               (return-from %btree-insert-in-inner-node :left-shift))
  975.                             ; The insert string won't fit. We have to do a recursive call
  976.                             (%copy-byte-array-portion
  977.                              parent-buf (+ parent-buf-offset left-offset left-entry-size) bytes-after-left-entry
  978.                              parent-buf (+ parent-buf-offset left-offset) parent-page)
  979.                             (fill.b (+ left-offset bytes-after-left-entry) 0 left-entry-size)
  980.                             (store.w (- parent-used left-entry-size) $btree_used)
  981.                             (store.w (+ parent-free left-entry-size) $btree_free)
  982.                             (store.w (1- (load.uw $btree_count)) $btree_count)
  983.                             (%btree-insert-in-inner-node
  984.                              disk-cache btree parent left-offset insert-string left-neighbor
  985.                              nil insert-length)
  986. ;                            (format t "~&Shuffled left inner node and inserted.")
  987. ;                            (check-btree-consistency disk-cache btree)
  988.                             (return-from %btree-insert-in-inner-node :left-shift-and-insert)))))))))
  989.             ; Didn't fit in left neighbor. Try right neighbor
  990.             (accessing-disk-cache (disk-cache parent)
  991.               (when (< (+ right-offset 4) (+ $btree_data parent-used))
  992.                 (setq right-entry-size (normalize-size (+ 5 (load.b (+ right-offset 4))) 4)
  993.                       right-neighbor (load.l (+ right-offset right-entry-size)))))
  994.             (when (eql $pheap-nil right-neighbor) (setq right-neighbor nil))
  995.             (when right-neighbor
  996. ;              (format t "~&Trying to shuffle right")
  997.               (require-satisfies dc-vector-subtype-p 
  998.                                  disk-cache right-neighbor $v_btree-node)
  999.               (accessing-disk-cache (disk-cache right-neighbor) 
  1000.                 (setq right-free (load.uw $btree_free)
  1001.                       right-used (load.uw $btree_used)))
  1002.               ; Almost a copy of the left-neighbor case above
  1003.               ; Debug that code, then modify it to go here.
  1004.               )))
  1005.         ; Can't slide stuff around. Need to split two nodes into three
  1006.         ; (or one node into two if it's the root)
  1007.         (when root-p
  1008.           ; We're passing a large amount of state.
  1009.           ; Maybe it would be better to recompute some of this stuff.
  1010.           (%btree-split-root
  1011.            disk-cache btree node offset key-string key-length value value-imm?
  1012.            size used free count flags sizes node-index)
  1013.           (return-from %btree-insert-in-inner-node :split-root))
  1014.         ; again, there's an awfully large amount of state here.
  1015.         (let ((normalized-offset (- offset $btree_data)))
  1016.           (declare (fixnum normalized-offset))
  1017.           (cond (left-neighbor
  1018.                  (%btree-split-inner-node
  1019.                   disk-cache btree key-string key-length value value-imm?
  1020.                   (the fixnum (+ normalized-offset left-used -4)) flags
  1021.                   parent left-offset left-entry-size
  1022.                   left-neighbor left-used left-free
  1023.                   node used free))
  1024.                 (right-neighbor
  1025.                  (%btree-split-inner-node
  1026.                   disk-cache btree key-string key-length value value-imm?
  1027.                   normalized-offset flags
  1028.                   parent right-offset right-entry-size
  1029.                   node used free
  1030.                   right-neighbor right-used right-free))
  1031.                 (t (error "Not root-p but no neighbors"))))
  1032.         (return-from %btree-insert-in-inner-node :split-node)))))
  1033.  
  1034. (defun %btree-split-root (disk-cache btree node offset key-string key-length value value-imm?
  1035.                                      size used free count flags sizes node-index)
  1036.   (declare (fixnum offset key-length size used free count flags))
  1037. ;  (break "Splitting root")
  1038.   (let* ((parent (dc-cons-btree-node
  1039.                   disk-cache btree btree (ash 1 $btree_flags.root-bit)))
  1040.          (new-flags (logand flags (lognot (ash 1 $btree_flags.root-bit))))
  1041.          (right-neighbor (dc-cons-btree-node disk-cache btree parent new-flags))
  1042.          (leaf-p (logbitp $btree_flags.leaf-bit flags))
  1043.          (save-used used))
  1044.     (declare (fixnum save-used))
  1045.     (with-locked-page (disk-cache node t node-buf node-buf-offset nil node-page)
  1046.       (declare (fixnum node-buf-offset))
  1047.       (with-locked-page (disk-cache right-neighbor t right-buf right-buf-offset nil right-page)
  1048.         (declare (fixnum right-buf-offset))
  1049.         (let* ((right-used 0)
  1050.                (right-free 0)
  1051.                (bytes-before-new (- offset $btree_data))
  1052.                (total-bytes 0)
  1053.                (bytes-to-keep 0)
  1054.                (bytes-to-copy 0)
  1055.                (max-bytes-to-keep 0)
  1056.                (last-size 0)
  1057.                (last-length 0)
  1058.                (split-index 0))
  1059.           (declare (fixnum right-used right-free
  1060.                            bytes-before-new total-bytes bytes-to-keep bytes-to-copy
  1061.                            max-bytes-to-keep last-size last-length split-index))
  1062.           (accessing-byte-array (right-buf right-buf-offset right-page)
  1063.             (setq right-used (load.uw $btree_used)
  1064.                   right-free (load.uw $btree_free)
  1065.                   total-bytes (+ used size)
  1066.                   max-bytes-to-keep (ash total-bytes -1)))
  1067.           (dotimes (i (1+ count)
  1068.                       (error "Didn't half fill new node on root split."))
  1069.             (when (>= (incf bytes-to-keep (setq last-size (svref sizes i)))
  1070.                       max-bytes-to-keep)
  1071.               (setq split-index i)
  1072.               (return)))
  1073.           (setq bytes-to-copy (- total-bytes bytes-to-keep))
  1074.           (incf right-free (the fixnum (- right-used bytes-to-copy)))
  1075.           (setq right-used bytes-to-copy)
  1076.           (let* ((ptr (+ node-buf-offset $btree_data bytes-to-keep))
  1077.                  (right-ptr (+ right-buf-offset $btree_data))
  1078.                  (new-went-right nil))
  1079.             (declare (fixnum ptr right-ptr))
  1080. ;            (break "About to copy to right-neighbor")
  1081.             (if (> bytes-to-keep bytes-before-new)
  1082.               (decf ptr size)
  1083.               (progn
  1084.                 (setq new-went-right t)
  1085.                 (%copy-byte-array-portion
  1086.                  node-buf ptr (decf bytes-before-new bytes-to-keep)
  1087.                  right-buf right-ptr right-page)
  1088.                 (incf ptr bytes-before-new)
  1089.                 (incf right-ptr bytes-before-new)
  1090.                 (decf bytes-to-copy bytes-before-new)
  1091.                 (%store-btree-entry 
  1092.                  right-buf right-ptr right-page key-string key-length value value-imm? size)
  1093.                 (incf right-ptr size)
  1094.                 (decf bytes-to-copy size)))
  1095.             (when (> bytes-to-copy 0)
  1096.               (%copy-byte-array-portion
  1097.                node-buf ptr bytes-to-copy right-buf right-ptr right-page)
  1098.               (incf ptr bytes-to-copy)
  1099.               (incf right-ptr bytes-to-copy))
  1100.             (accessing-byte-array (right-buf right-buf-offset right-page)
  1101.               (store.w right-used $btree_used)
  1102.               (store.w right-free $btree_free)
  1103.               (store.w (the fixnum (- count split-index)) $btree_count))
  1104.             (incf free (- used bytes-to-keep))
  1105.             (setq used bytes-to-keep)
  1106.             (unless new-went-right
  1107.               (setq ptr (+ node-buf-offset offset))
  1108.               (unless (eql split-index node-index)
  1109.                 (%copy-byte-array-portion
  1110.                  node-buf ptr (- used bytes-before-new)
  1111.                  node-buf (the fixnum (+ ptr size)) node-page))
  1112.               (%store-btree-entry 
  1113.                node-buf ptr node-page
  1114.                key-string key-length value value-imm? size))
  1115.             (setq last-length (- last-size 4))
  1116.             (with-locked-page (disk-cache parent t parent-buf parent-buf-offset nil parent-page)
  1117.               (accessing-byte-array (parent-buf nil parent-page)
  1118.                 (let ((p (+ parent-buf-offset $btree_data)))
  1119.                   (declare (fixnum p))
  1120.                   (store.l node p)
  1121.                   (incf p 4)
  1122.                   (setq ptr (+ node-buf-offset $btree_data used (- last-length)))
  1123.                   (%copy-byte-array-portion
  1124.                    node-buf ptr last-length parent-buf p)
  1125.                   (incf p last-length)
  1126.                   (incf ptr last-length)
  1127.                   (store.l right-neighbor p)))
  1128.               (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  1129.                 (let* ((parent-used (+ last-size 4))
  1130.                        (diff (- parent-used (load.uw $btree_used))))
  1131.                   (declare (fixnum parent-used diff))
  1132.                   (store.w parent-used $btree_used)
  1133.                   (store.w (the fixnum (- (load.uw $btree_free) diff)) $btree_free)
  1134.                   (store.w 1 $btree_count))))
  1135.             (if leaf-p
  1136.               (progn
  1137.                 (incf used 4)
  1138.                 (decf free 4)
  1139.                 (accessing-byte-array (node-buf nil node-page)
  1140.                   (store.l right-neighbor ptr))
  1141.                 (incf split-index))     ; leaves keep the parent's entry
  1142.               (progn
  1143.                 (decf used last-length)
  1144.                 (incf free last-length)))
  1145.             (accessing-byte-array (node-buf (+ node-buf-offset $btree_data) node-page)
  1146.               (fill.b used 0 (the fixnum (- save-used used)))))
  1147.           (accessing-byte-array (node-buf node-buf-offset node-page)
  1148.             (store.l parent $btree_parent)
  1149.             (store.w used $btree_used)
  1150.             (store.w free $btree_free)
  1151.             (store.w split-index $btree_count)
  1152.             (store.w new-flags $btree_flags)))))
  1153.     (accessing-disk-cache (disk-cache)
  1154.       (svset.p btree $btree.root parent)
  1155.       (svset.p btree $btree.depth (1+ (svref.p btree $btree.depth)) t))
  1156.     (unless leaf-p
  1157.       (%btree-update-childrens-parents disk-cache right-neighbor))
  1158. ;    (format t "~&Root is split")
  1159. ;    (check-btree-consistency disk-cache btree)
  1160.     parent))
  1161.  
  1162. ; Insert middle-string into parent before left-string.
  1163. ; Then left-string is guaranteed to fit in same parent node
  1164.  
  1165. (defun %btree-split-leaf-node
  1166.        (disk-cache btree key-string key-length value value-imm?
  1167.                    insert-offset flags
  1168.                    parent parent-offset parent-entry-size
  1169.                    left-node left-used left-free
  1170.                    right-node right-used right-free)
  1171.   (declare (fixnum key-length insert-offset parent-offset parent-entry-size
  1172.                    left-used left-free right-used right-free))
  1173. ;  (break "%split-btree-leaf-node")
  1174.   (with-locked-page (disk-cache parent t parent-buf parent-buf-offset nil parent-page)
  1175.     (declare (fixnum parent-buf-offset))
  1176.     (let ((new-parent-key-string (make-string 128))
  1177.           (new-parent-key-length 0)
  1178.           (middle-node (dc-cons-btree-node disk-cache btree parent flags)))
  1179.       (declare (dynamic-extent new-key-string)
  1180.                (fixnum new-parent-key-length))
  1181.       (with-locked-page (disk-cache left-node t left-buf left-buf-offset nil left-page)
  1182.         (declare (fixnum left-buf-offset))
  1183.         (with-locked-page (disk-cache right-node t right-buf right-buf-offset nil right-page)
  1184.           (declare (fixnum right-buf-offset))
  1185.           (let* ((left-count (accessing-byte-array (left-buf left-buf-offset)
  1186.                                (load.uw $btree_count)))
  1187.                  (right-count (accessing-byte-array (right-buf right-buf-offset)
  1188.                                 (load.uw $btree_count)))
  1189.                  (size (normalize-size (+ 5 key-length) 4))
  1190.                  (total-count (1+ (the fixnum (+ left-count right-count))))
  1191.                  (total-size (+ left-used right-used -4 size))
  1192.                  (target-size (ceiling total-size 3))
  1193.                  (sizes (make-array total-count))
  1194.                  (new-left-count 0)
  1195.                  (new-left-used 0)
  1196.                  (last-left-size 0)
  1197.                  (new-middle-count 0)
  1198.                  (new-middle-used-sans-parent 0)
  1199.                  (new-middle-used 0)
  1200.                  (last-middle-size 0)
  1201.                  (new-right-count 0)
  1202.                  (new-right-used 0)
  1203.                  (insert-goes-left (< insert-offset (- left-used 4))))
  1204.             (declare (fixnum left-count right-count size
  1205.                              total-count total-size target-size
  1206.                              new-left-count new-left-used last-left-size
  1207.                              new-middle-count new-middle-used-sans-parent new-middle-used last-middle-size
  1208.                              new-right-count new-right-used)
  1209.                      (dynamic-extent sizes))
  1210.             ; Fillin all-sizes with sizes from left-node, right-node, and key-string
  1211.             (%lookup-node-sizes
  1212.              disk-cache left-node sizes left-count
  1213.              (and insert-goes-left (+ insert-offset $btree_data))
  1214.              size)
  1215.             (%lookup-node-sizes
  1216.              disk-cache right-node sizes right-count
  1217.              (and (not insert-goes-left) (+ (- insert-offset (- left-used 4)) $btree_data))
  1218.              size (if insert-goes-left (1+ left-count) left-count))
  1219.             (let ((i 0))
  1220.               (loop
  1221.                 (incf new-left-used (setq last-left-size (aref sizes i)))
  1222.                 (incf new-left-count)
  1223.                 (incf i)
  1224.                 (when (>= new-left-used target-size)
  1225.                   (return)))
  1226.               (setq target-size (ash (- total-size new-left-used) -1))
  1227.               (loop
  1228.                 (incf new-middle-used (setq last-middle-size (aref sizes i)))
  1229.                 (incf new-middle-used-sans-parent last-middle-size)
  1230.                 (incf new-middle-count)
  1231.                 (incf i)
  1232.                 (when (>= new-middle-used target-size)
  1233.                   (return)))
  1234.               (setq new-right-used (- total-size new-left-used new-middle-used)
  1235.                     new-right-count (- total-count
  1236.                                        (the fixnum (+ new-left-count new-middle-count)))))
  1237.             (unless (and (>= left-used new-left-used) (>= right-used new-right-used))
  1238.               (error "One of the 2 full nodes was not full."))
  1239.             (with-locked-page (disk-cache middle-node t middle-buf middle-buf-offset nil middle-page)
  1240.               (declare (fixnum middle-buf-offset))
  1241.               (let* ((left-ptr (+ left-buf-offset $btree_data new-left-used))
  1242.                      (left-copy (- left-used new-left-used 4))          ; don't copy pointer to right node
  1243.                      (middle-ptr (+ middle-buf-offset $btree_data))
  1244.                      (right-copy (- right-used new-right-used))
  1245.                      (right-dont-copy new-right-used)
  1246.                      (right-ptr (+ right-buf-offset $btree_data))
  1247.                      (parent-string-ptr (+ parent-buf-offset parent-offset 4))
  1248.                      (parent-string-size (- parent-entry-size 4))
  1249.                      (insert-location nil))
  1250.                 (declare (fixnum left-ptr left-copy middle-ptr 
  1251.                                  right-copy right-dont-copy right-ptr
  1252.                                  parent-string-ptr parent-string-size))
  1253.                 ; Don't copy bytes that are for the new value/key-string
  1254.                 (cond ((< insert-offset new-left-used)
  1255.                        (setq insert-location :left)
  1256.                        (decf left-ptr size)
  1257.                        (incf left-copy size))
  1258.                       ((>= insert-offset (+ new-left-used new-middle-used-sans-parent))
  1259.                        (setq insert-location :right)
  1260.                        (incf right-copy size)
  1261.                        (decf right-dont-copy size))
  1262.                       (t (setq insert-location :middle)))
  1263.                 ; slide end of left buf to the middle one
  1264.                 (%copy-byte-array-portion
  1265.                  left-buf left-ptr left-copy middle-buf middle-ptr middle-page)
  1266.                 (incf middle-ptr left-copy)
  1267.                 ; and clear the now garbage bytes
  1268.                 (accessing-byte-array (left-buf nil left-page)
  1269.                   (fill.b left-ptr 0 (the fixnum (+ left-copy 4))))
  1270.                 ; copy the beginning of the right buffer to the middle one
  1271.                 (%copy-byte-array-portion
  1272.                  right-buf right-ptr right-copy middle-buf middle-ptr middle-page)
  1273.                 ; slide the remaining portion of the right buffer left
  1274.                 (%copy-byte-array-portion
  1275.                  right-buf (+ right-ptr right-copy) right-dont-copy
  1276.                  right-buf right-ptr right-page)
  1277.                 ; and clear the garbage.
  1278.                 (accessing-byte-array (right-buf nil right-page)
  1279.                   (fill.b (+ right-ptr right-dont-copy) 0 right-copy))
  1280. ;                (format t "~&New key went ~s" insert-location)
  1281.                 (ecase insert-location
  1282.                   (:left
  1283.                    (setq left-ptr (+ left-buf-offset $btree_data insert-offset))
  1284.                    (%copy-byte-array-portion
  1285.                     left-buf left-ptr (- left-used left-copy insert-offset)
  1286.                     left-buf (+ left-ptr size) left-page)
  1287.                    (%store-btree-entry left-buf left-ptr left-page
  1288.                                        key-string key-length value value-imm? size))
  1289.                   (:middle
  1290.                    (decf insert-offset new-left-used)
  1291.                    (setq middle-ptr (+ middle-buf-offset $btree_data insert-offset))
  1292.                    (%copy-byte-array-portion
  1293.                     middle-buf middle-ptr (- new-middle-used insert-offset size)
  1294.                     middle-buf (+ middle-ptr size) middle-page)
  1295.                    (%store-btree-entry middle-buf middle-ptr middle-page
  1296.                                        key-string key-length value value-imm? size))
  1297.                   (:right
  1298.                    (decf insert-offset (+ left-used -4 right-copy))
  1299.                    (setq right-ptr (+ right-buf-offset $btree_data insert-offset))
  1300.                    (%copy-byte-array-portion
  1301.                     right-buf right-ptr (- right-dont-copy insert-offset)
  1302.                     right-buf (+ right-ptr size) right-page)
  1303.                    (%store-btree-entry right-buf right-ptr right-page
  1304.                                        key-string key-length value value-imm? size)))
  1305.                 ; Put the last string in left-node & middle-node into parent.
  1306.                 (decf last-left-size 4)
  1307.                 (decf last-middle-size 4)
  1308.                 (let ((parent-used 0)
  1309.                       (parent-free 0)
  1310.                       (parent-diff (- last-middle-size parent-string-size)))
  1311.                   (declare (fixnum parent-used parent-free parent-diff))
  1312.                   (accessing-byte-array (parent-buf parent-buf-offset)
  1313.                     (setq parent-used (load.uw $btree_used)
  1314.                           parent-free (load.uw $btree_free)))
  1315.                   (setq left-ptr (+ left-buf-offset $btree_data (- new-left-used last-left-size))
  1316.                         middle-ptr (+ middle-buf-offset $btree_data 
  1317.                                       (- new-middle-used last-middle-size)))
  1318.                   (accessing-byte-array (left-buf)
  1319.                     (setq new-parent-key-length (load.b left-ptr)))
  1320.                   (%copy-byte-array-portion
  1321.                    left-buf (1+ left-ptr) new-parent-key-length new-parent-key-string 0)
  1322.                   (incf new-left-used 4)
  1323.                   (incf new-middle-used 4)
  1324.                   (accessing-byte-array (left-buf nil left-page)
  1325.                     (store.l middle-node (+ left-ptr last-left-size)))
  1326.                   (accessing-byte-array (middle-buf nil left-page)
  1327.                     (store.l right-node (+ middle-ptr last-middle-size)))
  1328.                   (accessing-byte-array (left-buf left-buf-offset left-page)
  1329.                     (decf left-free (- new-left-used left-used))
  1330.                     (store.w left-free $btree_free)
  1331.                     (store.w new-left-used $btree_used)
  1332.                     (store.w new-left-count $btree_count))
  1333.                   (accessing-byte-array (middle-buf middle-buf-offset middle-page)
  1334.                     (store.w (- (load.uw $btree_free) (- new-middle-used (load.uw $btree_used)))
  1335.                              $btree_free)
  1336.                     (store.w new-middle-used $btree_used)
  1337.                     (store.w new-middle-count $btree_count))
  1338.                   (accessing-byte-array (right-buf right-buf-offset right-page)
  1339.                     (decf right-free (- new-right-used right-used))
  1340.                     (store.w right-free $btree_free)
  1341.                     (store.w new-right-used $btree_used)
  1342.                     (store.w new-right-count $btree_count))
  1343.                   (let* ((parent-string-offset (- parent-string-ptr $btree_data parent-buf-offset))
  1344.                          (parent-after-string (- parent-used parent-string-offset parent-string-size)))
  1345.                       (declare (fixnum parent-string-offset parent-after-string))
  1346.                     (if (>= parent-free parent-diff)
  1347.                       ; The new left-node entry fits in the parent
  1348.                       (progn
  1349. ;                        (format t "~&New middle-node fits")
  1350.                         (%copy-byte-array-portion
  1351.                          parent-buf (+ parent-string-ptr parent-string-size) parent-after-string
  1352.                          parent-buf (+ parent-string-ptr last-middle-size) parent-page)
  1353.                         (accessing-byte-array (parent-buf nil parent-page)
  1354.                           (store.l middle-node (the fixnum (- parent-string-ptr 4))))
  1355.                         (%copy-byte-array-portion
  1356.                          middle-buf middle-ptr last-middle-size
  1357.                          parent-buf parent-string-ptr parent-page)
  1358.                         (incf parent-used parent-diff)
  1359.                         (decf parent-free parent-diff)
  1360.                         (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  1361.                           (store.w parent-used $btree_used)
  1362.                           (store.w parent-free $btree_free)
  1363.                           (when (< parent-diff 0)
  1364.                             (fill.b (+ $btree_data parent-used) 0 (- parent-diff)))))
  1365.                       ; the new middle-node entry doesn't fit. Must insert it the hard way
  1366.                       (let* ((last-middle-string-size (accessing-byte-array (middle-buf) (load.b middle-ptr)))
  1367.                              (last-middle-string (make-string last-middle-string-size))
  1368.                              (parent-ptr (- parent-string-ptr 4)))
  1369.                         (declare (dynamic-extent last-middle-string)
  1370.                                  (fixnum parent-ptr last-middle-string-size))
  1371. ;                        (format t "~&New middle-node didn't fit: %btree-split-leaf-node.")
  1372.                         (decf parent-used parent-entry-size)
  1373.                         (incf parent-free parent-entry-size)
  1374.                         (%copy-byte-array-portion
  1375.                          parent-buf (+ parent-ptr parent-entry-size) parent-after-string
  1376.                          parent-buf parent-ptr parent-page)
  1377.                         (accessing-byte-array (parent-buf nil parent-page)
  1378.                           (fill.b (+ parent-ptr parent-after-string) 0 parent-entry-size))
  1379.                         (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  1380.                           (store.w parent-used $btree_used)
  1381.                           (store.w parent-free $btree_free)
  1382.                           (store.w (1- (load.uw $btree_count)) $btree_count))
  1383.                         (%copy-byte-array-portion
  1384.                          middle-buf (1+ middle-ptr) last-middle-string-size last-middle-string 0)
  1385.                         (%btree-insert-in-inner-node
  1386.                          disk-cache btree parent parent-offset
  1387.                          last-middle-string middle-node nil last-middle-string-size)
  1388.                         ; parent may have changed.
  1389.                         (setq parent (accessing-byte-array (middle-buf middle-buf-offset)
  1390.                                        (load.l $btree_parent))
  1391.                               parent-offset (%btree-search-for-subnode
  1392.                                              disk-cache parent middle-node))
  1393.                         (accessing-byte-array (left-buf left-buf-offset left-page)
  1394.                           (unless (eql parent (load.l $btree_parent))
  1395.                             (store.l parent $btree_parent))))))))))))
  1396.       ; finally, we can insert the new key in the (possibly new) parent
  1397.       (%btree-insert-in-inner-node disk-cache btree parent parent-offset
  1398.                                    new-parent-key-string left-node nil new-parent-key-length)
  1399. ;      (format t "~&End of %btree-split-leaf-node: #x~x #x~x" left-node right-node)
  1400. ;      (check-btree-consistency disk-cache btree)
  1401.       )))
  1402.  
  1403. (defun %btree-split-inner-node
  1404.        (disk-cache btree key-string key-length value value-imm?
  1405.                    insert-offset flags
  1406.                    parent parent-offset parent-entry-size
  1407.                    left-node left-used left-free
  1408.                    right-node right-used right-free)
  1409.   (declare (fixnum key-length insert-offset parent-offset parent-entry-size
  1410.                    left-used left-free right-used right-free))
  1411. ;  (break "%btree-split-inner-node")
  1412.   (with-locked-page (disk-cache parent t parent-buf parent-buf-offset nil parent-page)
  1413.     (declare (fixnum parent-buf-offset))
  1414.     (let ((new-parent-key-string (make-string 128))
  1415.           (new-parent-key-length 0)
  1416.           (middle-node (dc-cons-btree-node disk-cache btree parent flags)))
  1417.       (declare (dynamic-extent new-key-string)
  1418.                (fixnum new-parent-key-length))
  1419.       (with-locked-page (disk-cache left-node t left-buf left-buf-offset nil left-page)
  1420.         (declare (fixnum left-buf-offset))
  1421.         (with-locked-page (disk-cache right-node t right-buf right-buf-offset nil right-page)
  1422.           (declare (fixnum right-buf-offset))
  1423.           (let* ((left-count (accessing-byte-array (left-buf left-buf-offset)
  1424.                                (load.uw $btree_count)))
  1425.                  (right-count (accessing-byte-array (right-buf right-buf-offset)
  1426.                                 (load.uw $btree_count)))
  1427.                  (size (normalize-size (+ 5 key-length) 4))
  1428.                  (total-count (1+ (the fixnum (+ left-count right-count))))
  1429.                  (total-size (+ left-used parent-entry-size right-used -4 size))
  1430.                  (target-size (ceiling total-size 3))
  1431.                  (sizes (make-array total-count))
  1432.                  (new-left-count 0)
  1433.                  (new-left-used 0)
  1434.                  (last-left-size 0)
  1435.                  (new-middle-count 0)
  1436.                  (new-middle-used-sans-parent 0)
  1437.                  (new-middle-used 0)
  1438.                  (last-middle-size 0)
  1439.                  (new-right-count 0)
  1440.                  (new-right-used 0)
  1441.                  (insert-goes-left (< insert-offset (- left-used 4))))
  1442.             (declare (fixnum left-count right-count size
  1443.                              total-count total-size target-size
  1444.                              new-left-count new-left-used last-left-size
  1445.                              new-middle-count new-middle-used-sans-parent new-middle-used last-middle-size
  1446.                              new-right-count new-right-used)
  1447.                      (dynamic-extent sizes))
  1448.             ; Fillin all-sizes with sizes from left-node, right-node, and key-string
  1449.             (%lookup-node-sizes
  1450.              disk-cache left-node sizes left-count
  1451.              (and insert-goes-left (+ insert-offset $btree_data))
  1452.              size)
  1453.             (%lookup-node-sizes
  1454.              disk-cache right-node sizes right-count
  1455.              (and (not insert-goes-left) (+ (- insert-offset (- left-used 4)) $btree_data))
  1456.              size (if insert-goes-left (1+ left-count) left-count))
  1457.             (let ((i 0))
  1458.               (loop
  1459.                 (incf new-left-used (setq last-left-size (aref sizes i)))
  1460.                 (incf new-left-count)
  1461.                 (incf i)
  1462.                 (when (>= new-left-used target-size)
  1463.                   (return)))
  1464.               (setq target-size (ash (- total-size new-left-used) -1))
  1465.               (setq new-middle-used parent-entry-size)
  1466.               (loop
  1467.                 (incf new-middle-used (setq last-middle-size (aref sizes i)))
  1468.                 (incf new-middle-used-sans-parent last-middle-size)
  1469.                 (incf new-middle-count)
  1470.                 (incf i)
  1471.                 (when (>= new-middle-used target-size)
  1472.                   (return)))
  1473.               (setq new-right-used (- total-size new-left-used new-middle-used)
  1474.                     new-right-count (- total-count (+ new-left-count new-middle-count))))
  1475.             (unless (and (>= left-used new-left-used) (>= right-used new-right-used))
  1476.               (error "One of the 2 full nodes was not full."))
  1477.             (with-locked-page (disk-cache middle-node t middle-buf middle-buf-offset nil middle-page)
  1478.               (declare (fixnum middle-buf-offset))
  1479.               (let* ((left-ptr (+ left-buf-offset $btree_data new-left-used))
  1480.                      (left-copy (- left-used new-left-used))
  1481.                      (middle-ptr (+ middle-buf-offset $btree_data))
  1482.                      (right-copy (- right-used new-right-used))
  1483.                      (right-dont-copy new-right-used)
  1484.                      (right-ptr (+ right-buf-offset $btree_data))
  1485.                      (parent-string-ptr (+ parent-buf-offset parent-offset 4))
  1486.                      (parent-string-size (- parent-entry-size 4))
  1487.                      (insert-location nil))
  1488.                 (declare (fixnum left-ptr left-copy middle-ptr 
  1489.                                  right-copy right-dont-copy right-ptr
  1490.                                  parent-string-ptr parent-string-size))
  1491.                 ; Don't copy bytes that are for the new value/key-string
  1492.                 (cond ((< insert-offset new-left-used)
  1493.                        (setq insert-location :left)
  1494.                        (decf left-ptr size)
  1495.                        (incf left-copy size))
  1496.                       ((>= insert-offset (+ new-left-used new-middle-used-sans-parent))
  1497.                        (setq insert-location :right)
  1498.                        (incf right-copy size)
  1499.                        (decf right-dont-copy size))
  1500.                       (t (setq insert-location :middle)))
  1501.                 ; slide end of left buf to the middle one
  1502.                 (%copy-byte-array-portion
  1503.                  left-buf left-ptr left-copy middle-buf middle-ptr middle-page)
  1504.                 (incf middle-ptr left-copy)
  1505.                 ; and clear the now garbage bytes
  1506.                 (accessing-byte-array (left-buf nil left-page)
  1507.                   (fill.b left-ptr 0 left-copy))
  1508.                 ; unless we're at the leaves, copy the parent entry into the middle node
  1509.                 (%copy-byte-array-portion
  1510.                  parent-buf parent-string-ptr parent-string-size
  1511.                  middle-buf middle-ptr middle-page)
  1512.                 (incf middle-ptr parent-string-size)
  1513.                 ; copy the beginning of the right buffer to the middle one
  1514.                 (%copy-byte-array-portion
  1515.                  right-buf right-ptr right-copy middle-buf middle-ptr middle-page)
  1516.                 ; slide the remaining portion of the right buffer left
  1517.                 (%copy-byte-array-portion
  1518.                  right-buf (+ right-ptr right-copy) right-dont-copy
  1519.                  right-buf right-ptr right-page)
  1520.                 ; and clear the garbage.
  1521.                 (accessing-byte-array (right-buf nil right-page)
  1522.                   (fill.b (+ right-ptr right-dont-copy) 0 right-copy))
  1523. ;                (format t "~&New key went ~s" insert-location)
  1524.                 (ecase insert-location
  1525.                   (:left
  1526.                    (setq left-ptr (+ left-buf-offset $btree_data insert-offset))
  1527.                    (%copy-byte-array-portion
  1528.                     left-buf left-ptr (- left-used left-copy insert-offset)
  1529.                     left-buf (+ left-ptr size) left-page)
  1530.                    (%store-btree-entry left-buf left-ptr left-page
  1531.                                        key-string key-length value value-imm? size))
  1532.                   (:middle
  1533.                    (decf insert-offset new-left-used)
  1534.                    (unless insert-goes-left
  1535.                      (incf insert-offset parent-entry-size))
  1536.                    (setq middle-ptr (+ middle-buf-offset $btree_data insert-offset))
  1537.                    (%copy-byte-array-portion
  1538.                     middle-buf middle-ptr (- new-middle-used insert-offset size)
  1539.                     middle-buf (+ middle-ptr size) middle-page)
  1540.                    (%store-btree-entry middle-buf middle-ptr middle-page
  1541.                                        key-string key-length value value-imm? size))
  1542.                   (:right
  1543.                    (decf insert-offset (+ left-used -4 right-copy))
  1544.                    (setq right-ptr (+ right-buf-offset $btree_data insert-offset))
  1545.                    (%copy-byte-array-portion
  1546.                     right-buf right-ptr (- right-dont-copy insert-offset)
  1547.                     right-buf (+ right-ptr size) right-page)
  1548.                    (%store-btree-entry right-buf right-ptr right-page
  1549.                                        key-string key-length value value-imm? size)))
  1550.                 ; Put the last string in left-node & middle-node into parent.
  1551.                 (decf last-left-size 4)
  1552.                 (decf last-middle-size 4)
  1553.                 (let ((parent-used 0)
  1554.                       (parent-free 0)
  1555.                       (parent-diff (- last-middle-size parent-string-size)))
  1556.                   (declare (dynamic-extent last-middle-string)
  1557.                            (fixnum parent-used parent-free parent-diff))
  1558.                   (accessing-byte-array (parent-buf parent-buf-offset)
  1559.                     (setq parent-used (load.uw $btree_used)
  1560.                           parent-free (load.uw $btree_free)))
  1561.                   (setq left-ptr (+ left-buf-offset $btree_data (- new-left-used last-left-size))
  1562.                         middle-ptr (+ middle-buf-offset $btree_data 
  1563.                                       (- new-middle-used last-middle-size)))
  1564.                   (accessing-byte-array (left-buf)
  1565.                     (setq new-parent-key-length (load.b left-ptr)))
  1566.                   (%copy-byte-array-portion
  1567.                    left-buf (1+ left-ptr) new-parent-key-length new-parent-key-string 0)
  1568.                   (decf new-left-used last-left-size)
  1569.                   (decf new-left-count)
  1570.                   (decf new-middle-used last-middle-size)
  1571.                   (accessing-byte-array (left-buf nil middle-page)
  1572.                     (fill.b left-ptr 0 last-left-size))
  1573.                   (accessing-byte-array (left-buf left-buf-offset left-page)
  1574.                     (decf left-free (- new-left-used left-used))
  1575.                     (store.w left-free $btree_free)
  1576.                     (store.w new-left-used $btree_used)
  1577.                     (store.w new-left-count $btree_count))
  1578.                   (accessing-byte-array (middle-buf middle-buf-offset middle-page)
  1579.                     (store.w (- (load.uw $btree_free) (- new-middle-used (load.uw $btree_used)))
  1580.                              $btree_free)
  1581.                     (store.w new-middle-used $btree_used)
  1582.                     (store.w new-middle-count $btree_count))
  1583.                   (accessing-byte-array (right-buf right-buf-offset right-page)
  1584.                     (decf right-free (- new-right-used right-used))
  1585.                     (store.w right-free $btree_free)
  1586.                     (store.w new-right-used $btree_used)
  1587.                     (store.w new-right-count $btree_count))
  1588.                   (let* ((parent-string-offset (- parent-string-ptr $btree_data parent-buf-offset))
  1589.                          (parent-after-string (- parent-used parent-string-offset parent-string-size)))
  1590.                       (declare (fixnum parent-string-offset parent-after-string))
  1591.                     (if (>= parent-free parent-diff)
  1592.                       ; The new left-node entry fits in the parent
  1593.                       (progn
  1594. ;                        (format t "~&New middle-node fits: %btree-split-inner-node")
  1595.                         (%copy-byte-array-portion
  1596.                          parent-buf (+ parent-string-ptr parent-string-size) parent-after-string
  1597.                          parent-buf (+ parent-string-ptr last-middle-size) parent-page)
  1598.                         (accessing-byte-array (parent-buf nil parent-page)
  1599.                           (store.l middle-node (the fixnum (- parent-string-ptr 4))))
  1600.                         (%copy-byte-array-portion
  1601.                          middle-buf middle-ptr last-middle-size
  1602.                          parent-buf parent-string-ptr parent-page)
  1603.                         (incf parent-used parent-diff)
  1604.                         (decf parent-free parent-diff)
  1605.                         (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  1606.                           (store.w parent-used $btree_used)
  1607.                           (store.w parent-free $btree_free)
  1608.                           (when (< parent-diff 0)
  1609.                             (fill.b (+ $btree_data parent-used) 0 (- parent-diff)))))
  1610.                       ; the new middle-node entry doesn't fit. Must insert it the hard way
  1611.                       (let* ((last-middle-string-size (accessing-byte-array (middle-buf)
  1612.                                                         (load.b left-ptr)))
  1613.                              (last-middle-string (make-string last-middle-string-size))
  1614.                              (parent-ptr (- parent-string-ptr 4)))
  1615.                         (declare (dynamic-extent last-middle-string)
  1616.                                  (fixnum parent-ptr last-middle-string-size))
  1617. ;                        (format t "~&New middle-node didn't fit: %btree-split-inner-node.")
  1618.                         (decf parent-used parent-entry-size)
  1619.                         (incf parent-free parent-entry-size)
  1620.                         (decf parent-string-offset 4)
  1621.                         (%copy-byte-array-portion
  1622.                          parent-buf (+ parent-ptr parent-entry-size) parent-after-string
  1623.                          parent-buf parent-ptr parent-page)
  1624.                         (accessing-byte-array (parent-buf nil parent-page)
  1625.                           (fill.b (+ parent-ptr parent-after-string) 0 parent-entry-size))
  1626.                         (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  1627.                           (store.w parent-used $btree_used)
  1628.                           (store.w parent-free $btree_free)
  1629.                           (store.w (1- (load.uw $btree_count)) $btree_count))
  1630.                         (%copy-byte-array-portion
  1631.                          middle-buf (1+ middle-ptr) last-middle-string-size last-middle-string 0)
  1632.                         (%btree-insert-in-inner-node
  1633.                          disk-cache btree parent parent-offset
  1634.                          last-middle-string middle-node nil last-middle-string-size)
  1635.                         ; parent may have changed.
  1636.                         (setq parent (accessing-byte-array (middle-buf middle-buf-offset)
  1637.                                        (load.l $btree_parent))
  1638.                               parent-offset (%btree-search-for-subnode
  1639.                                              disk-cache parent middle-node))
  1640.                         (accessing-byte-array (left-buf left-buf-offset left-page)
  1641.                           (unless (eql parent (load.l $btree_parent))
  1642.                             (store.l parent $btree_parent)))))
  1643.                     (accessing-byte-array (middle-buf nil left-page)
  1644.                       (fill.b middle-ptr 0 last-middle-size))))
  1645.                 (%btree-update-childrens-parents disk-cache middle-node))))))
  1646.       ; finally, we can insert the new key in the (possibly new) parent
  1647.       (%btree-insert-in-inner-node disk-cache btree parent parent-offset
  1648.                                    new-parent-key-string left-node nil new-parent-key-length)
  1649. ;      (format t "~&End of %btree-split-inner-node: #x~x #x~x" left-node right-node)
  1650. ;      (check-btree-consistency disk-cache btree)
  1651.       )))
  1652.  
  1653. ;; Store a single entry into a buffer.
  1654. (defun %store-btree-entry (buf offset page string string-length value value-imm? &optional size)
  1655.   (declare (fixnum offset string-length))
  1656.   (let ((p offset))
  1657.     (declare (fixnum p))
  1658.     (accessing-byte-array (buf nil page)
  1659.       (store.p value p value-imm?)
  1660.       (store.b string-length (incf p 4))
  1661.       (store.string string (incf p 1) string-length)
  1662.       (incf p string-length)
  1663.       (let* ((bytes (+ 5 string-length))
  1664.              (filler (- (or size (setq size (normalize-size bytes 4)))
  1665.                         bytes)))
  1666.         (declare (fixnum bytes filler))
  1667.         (when (> filler 0)
  1668.           ; This is for us poor humans.
  1669.           (fill.b p 0 filler)))))
  1670.   size)
  1671.  
  1672.  
  1673. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1674. ;;
  1675. ;; Code to support deletion
  1676.  
  1677. (defun %btree-delete-from-node (disk-cache btree node offset leaf-p)
  1678.   (declare (fixnum offset))
  1679.   (with-locked-page (disk-cache node t node-buf node-buf-offset nil node-page)
  1680.     (accessing-byte-array (node-buf node-buf-offset node-page)
  1681.       (let* ((ptr (+ node-buf-offset offset))
  1682.              (size (normalize-size (+ 5 (accessing-byte-array (node-buf)
  1683.                                           (load.b (+ ptr 4))))
  1684.                                    4))
  1685.              (used (load.uw $btree_used))
  1686.              (free (load.uw $btree_free))
  1687.              (count (load.uw $btree_count))
  1688.              (bytes-after-entry (- used size (- offset $btree_data))))
  1689.         (declare (fixnum ptr size used free count bytes-after-entry))
  1690.         (unless leaf-p
  1691.           (incf ptr 4)                  ; not a mistake. Look how it's called.
  1692.           (decf bytes-after-entry 4))
  1693.         (%copy-byte-array-portion node-buf (+ ptr size) bytes-after-entry
  1694.                                   node-buf ptr node-page)
  1695.         (accessing-byte-array (node-buf nil node-page)
  1696.           (fill.b (+ ptr bytes-after-entry) 0 size))
  1697.         (store.w (decf used size) $btree_used)
  1698.         (store.w (incf free size) $btree_free)
  1699.         (store.w (decf count) $btree_count)
  1700.         ; If this is the right-most entry in a leaf node, we could add here
  1701.         ; to find the entry higher in the tree and replace it.
  1702.         ; Probably not worth the effort.
  1703.         (when (<= used free)
  1704.           ; This node is <= half full. Try to merge or balance with a neighbor
  1705.           (let* ((parent (load.l $btree_parent))
  1706.                  left-offset middle-offset right-offset
  1707.                  left-neighbor right-neighbor
  1708.                  (parent-used 0)
  1709.                  (left-free 0)
  1710.                  (right-free 0))
  1711.             (declare (fixnum parent-used left-free right-free))
  1712.             (if (eql parent btree)
  1713.               ; This is the root. Nothing to do unless it's empty
  1714.               (when (eql count 0)
  1715.                 (let ((new-root (accessing-byte-array (node-buf node-buf-offset)
  1716.                                   (unless (logbitp $btree_flags.leaf-bit (load.uw $btree_flags))
  1717.                                     (load.l $btree_data)))))
  1718.                   (when new-root
  1719.                     (with-locked-page (disk-cache new-root t buf offset nil page)
  1720.                       (accessing-byte-array (buf offset)
  1721.                         (store.l btree $btree_parent)
  1722.                         (store.w (logior (ash 1 $btree_flags.root-bit) (load.uw $btree_flags))
  1723.                                  $btree_flags)))
  1724.                     ; Really need to lock this vector before doing any updating
  1725.                     (accessing-disk-cache (disk-cache)
  1726.                       (svset.p btree $btree.root new-root))
  1727. ;                    (break "Deleted root node")
  1728.                     (dc-free-btree-node disk-cache btree node))))
  1729.               (with-locked-page (disk-cache parent nil parent-buf parent-buf-offset)
  1730.                 (multiple-value-setq (middle-offset left-offset)
  1731.                   (%btree-search-for-subnode disk-cache parent node))
  1732.                 (unless middle-offset
  1733.                   (error "Couldn't find #x~x in #x~x in ~s" node parent disk-cache))
  1734.                 (accessing-byte-array (parent-buf parent-buf-offset)
  1735.                   (setq parent-used (load.uw $btree_used))
  1736.                   (when left-offset
  1737.                     (setq left-neighbor (load.l left-offset))
  1738.                     (accessing-disk-cache (disk-cache left-neighbor)
  1739.                       (setq left-free (load.uw $btree_free))))
  1740.                   (unless (>= middle-offset (+ $btree_data parent-used -4))
  1741.                     (setq right-offset (+ middle-offset
  1742.                                           (normalize-size (+ 5 (load.b (+ 4 middle-offset)))
  1743.                                                           4))
  1744.                           right-neighbor (load.l right-offset))
  1745.                     (accessing-disk-cache (disk-cache right-neighbor)
  1746.                       (setq right-free (load.uw $btree_free)))))
  1747.                 (let ((balance-function (if leaf-p
  1748.                                           '%balance-leaf-node-after-deletion
  1749.                                           '%balance-inner-node-after-deletion)))
  1750.                   (cond ((and left-neighbor (>= left-free right-free))
  1751.                          (funcall balance-function
  1752.                                   disk-cache btree left-neighbor left-free node free
  1753.                                   parent left-offset))
  1754.                         (right-neighbor
  1755.                          (funcall balance-function
  1756.                                   disk-cache btree node free right-neighbor right-free
  1757.                                   parent middle-offset))))))))))))
  1758.  
  1759. (defun %balance-leaf-node-after-deletion
  1760.        (disk-cache btree left-node left-free right-node right-free parent-node parent-offset)
  1761.   (declare (fixnum left-free right-free parent-offset))
  1762.   (with-locked-page (disk-cache parent-node t parent-buf parent-buf-offset nil parent-page)
  1763.     (with-locked-page (disk-cache left-node t left-buf left-buf-offset nil left-page)
  1764.       (with-locked-page (disk-cache right-node t right-buf right-buf-offset nil right-page)
  1765.         (let ((left-used 0)
  1766.               (left-count 0)
  1767.               (right-used 0)
  1768.               (right-count 0))
  1769.           (declare (fixnum left-used left-count right-used right-count))
  1770.           (accessing-byte-array (left-buf left-buf-offset)
  1771.             (setq left-used (load.uw $btree_used)
  1772.                   left-count (load.uw $btree_count)))
  1773.           (accessing-byte-array (right-buf right-buf-offset)
  1774.             (setq right-used (load.uw $btree_used)
  1775.                   right-count (load.uw $btree_count)))
  1776.           (let ((total-size (+ left-used right-used -4))
  1777.                 (space-available (+ left-used left-free)))
  1778.             (declare (fixnum total-size space-available))
  1779.             (if (<= total-size space-available)
  1780.               (progn
  1781.                 ; Can merge the two nodes
  1782.                 (%copy-byte-array-portion
  1783.                  right-buf (+ right-buf-offset $btree_data) right-used
  1784.                  left-buf (+ left-buf-offset $btree_data left-used -4))
  1785.                 (decf left-free (- total-size left-used))
  1786.                 (setq left-used total-size)
  1787.                 (incf left-count right-count)
  1788.                 (accessing-byte-array (left-buf left-buf-offset left-page)
  1789.                   (store.w left-used $btree_used)
  1790.                   (store.w left-free $btree_free)
  1791.                   (store.w left-count $btree_count))
  1792.                 (%btree-delete-from-node disk-cache btree parent-node parent-offset nil)
  1793.                 (dc-free-btree-node disk-cache btree right-node)
  1794.                 :merged)
  1795.               (progn
  1796.                 ; Can't merge so balance as well as we can.
  1797.                 (incf total-size 4)     ; restore the pointer form left-node to right-node
  1798.                 (let* ((total-count (+ left-count right-count))
  1799.                        (sizes (make-array total-count))
  1800.                        (target-size (ash total-size -1))
  1801.                        (new-left-used 4)
  1802.                        (new-right-used 0)
  1803.                        (used-diff 0)
  1804.                        (split-index 0))
  1805.                   (declare (fixnum total-count target-size new-left-used new-right-used
  1806.                                    used-diff split-index)
  1807.                            (dynamic-extent sizes))
  1808.                   (%lookup-node-sizes disk-cache left-node sizes left-count)
  1809.                   (%lookup-node-sizes
  1810.                    disk-cache right-node sizes right-count nil nil left-count)
  1811.                   (dotimes (i total-count (error "Should have merged"))
  1812.                     (incf new-left-used (svref sizes i))
  1813.                     (when (>= new-left-used target-size)
  1814.                       (setq split-index i)
  1815.                       (return)))
  1816.                   (setq used-diff (- new-left-used left-used))
  1817.                   (unless (eql used-diff 0)
  1818.                     (setq new-right-used (- right-used used-diff))
  1819.                     (if (> used-diff 0)
  1820.                       (let ((left-ptr (+ left-buf-offset $btree_data left-used -4))
  1821.                             (right-ptr (+ right-buf-offset $btree_data)))
  1822.                         (declare (fixnum left-ptr right-ptr))
  1823.                         (%copy-byte-array-portion
  1824.                          right-buf right-ptr used-diff left-buf left-ptr left-page)
  1825.                         (incf left-ptr used-diff)
  1826.                         (accessing-byte-array (left-buf nil left-page)
  1827.                           (store.l right-node left-ptr))
  1828.                         (%copy-byte-array-portion
  1829.                          right-buf (+ right-ptr used-diff) new-right-used
  1830.                          right-buf right-ptr right-page)
  1831.                         (incf right-ptr new-right-used)
  1832.                         (accessing-byte-array (right-buf nil right-page)
  1833.                           (fill.b right-ptr 0 used-diff)))
  1834.                       (let ((diff-used (- used-diff))
  1835.                             (left-ptr (+ left-buf-offset $btree_data new-left-used -4))
  1836.                             (right-ptr (+ right-buf-offset $btree_data)))
  1837.                         (declare (fixnum diff-used left-ptr right-ptr))
  1838.                         (%copy-byte-array-portion
  1839.                          right-buf right-ptr right-used
  1840.                          right-buf (+ right-ptr diff-used) right-page)
  1841.                         (%copy-byte-array-portion
  1842.                          left-buf left-ptr diff-used right-buf right-ptr right-page)
  1843.                         (accessing-byte-array (left-buf nil left-page)
  1844.                           (fill.b left-ptr 0 (+ diff-used 4))
  1845.                           (store.l right-node left-ptr))))
  1846.                     (decf left-free used-diff)
  1847.                     (incf right-free used-diff)
  1848.                     (setq left-count (1+ split-index)
  1849.                           right-count (- total-count left-count))
  1850.                     (accessing-byte-array (left-buf left-buf-offset)
  1851.                       (store.w new-left-used $btree_used)
  1852.                       (store.w left-free $btree_free)
  1853.                       (store.w left-count $btree_count))
  1854.                     (accessing-byte-array (right-buf right-buf-offset)
  1855.                       (store.w new-right-used $btree_used)
  1856.                       (store.w right-free $btree_free)
  1857.                       (store.w right-count $btree_count))
  1858.                     (let* ((last-left-size (svref sizes split-index))
  1859.                            (left-ptr (- (+ left-buf-offset $btree_data new-left-used)
  1860.                                         last-left-size))
  1861.                            (parent-entry-size 0)
  1862.                            (size-diff 0)
  1863.                            (parent-used 0)
  1864.                            (parent-free 0))
  1865.                       (declare (fixnum last-left-size left-ptr parent-entry-size
  1866.                                        size-diff parent-free parent-used))
  1867.                       (accessing-byte-array (parent-buf parent-buf-offset)
  1868.                         (setq parent-entry-size (normalize-size
  1869.                                                  (+ 5 (load.b (+ parent-offset 4)))
  1870.                                                  4)
  1871.                               size-diff (- last-left-size parent-entry-size)
  1872.                               parent-used (load.uw $btree_used)
  1873.                               parent-free (load.uw $btree_free)))
  1874.                       (if (>= parent-free size-diff)
  1875.                         ; Modified parent-entry fits
  1876.                         (let ((parent-ptr (+ parent-buf-offset parent-offset))
  1877.                               (new-parent-used (+ parent-used size-diff)))
  1878.                           (declare (fixnum parent-ptr new-parent-used))
  1879.                           (%copy-byte-array-portion
  1880.                            parent-buf (+ parent-ptr parent-entry-size)
  1881.                            (- parent-used (- parent-offset $btree_data) parent-entry-size)
  1882.                            parent-buf (+ parent-ptr last-left-size) parent-page)
  1883.                           (when (< size-diff 0)
  1884.                             (accessing-byte-array (parent-buf nil parent-page)
  1885.                               (fill.b (+ parent-buf-offset $btree_data new-parent-used)
  1886.                                       0 (- size-diff))))
  1887.                           (incf parent-ptr 4)
  1888.                           (decf last-left-size 4)
  1889.                           (%copy-byte-array-portion
  1890.                            left-buf left-ptr last-left-size
  1891.                            parent-buf parent-ptr parent-page)
  1892.                           (decf parent-free size-diff)
  1893.                           (accessing-byte-array (parent-buf parent-buf-offset)
  1894.                             (store.w new-parent-used $btree_used)
  1895.                             (store.w parent-free $btree_free)))
  1896.                         ; Modified parent-entry doesn't fit
  1897.                         (let ((parent-ptr (+ parent-buf-offset parent-offset))
  1898.                               (new-parent-used (- parent-used parent-entry-size)))
  1899.                           (%copy-byte-array-portion
  1900.                            parent-buf (+ parent-ptr parent-entry-size)
  1901.                            (- parent-used (- parent-offset $btree_data) parent-entry-size)
  1902.                            parent-buf parent-ptr parent-page)
  1903.                           (incf parent-free parent-entry-size)
  1904.                           (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  1905.                             (fill.b (+ $btree_data new-parent-used) 0 parent-entry-size)
  1906.                             (store.w new-parent-used $btree_used)
  1907.                             (store.w parent-free $btree_free)
  1908.                             (store.w (1- (load.uw $btree_count)) $btree_count))
  1909.                           (let* ((key-length (accessing-byte-array (left-buf)
  1910.                                                (load.b left-ptr)))
  1911.                                  (key-string (make-string key-length)))
  1912.                             (declare (fixnum key-length)
  1913.                                      (dynamic-extent key-string))
  1914.                             (%copy-byte-array-portion
  1915.                              left-buf (incf left-ptr) key-length key-string 0)
  1916.                             (%btree-insert-in-inner-node
  1917.                              disk-cache btree parent-node parent-offset
  1918.                              key-string left-node nil key-length)))))))
  1919.                 :balanced))))))))
  1920.  
  1921. ; Node 7e01 is ready to call this to merge.
  1922. ; Tested  (< left-used-diff 0) case
  1923. ; Need to test (>= left-used-diff 0) case.
  1924. ; c-x c-e here and eval the advice at the bottom of the file
  1925. ;
  1926. (defun %balance-inner-node-after-deletion
  1927.        (disk-cache btree left-node left-free right-node right-free parent-node parent-offset)
  1928.   (declare (fixnum left-free right-free parent-offset))
  1929.   (with-locked-page (disk-cache parent-node t parent-buf parent-buf-offset nil parent-page)
  1930.     (with-locked-page (disk-cache left-node t left-buf left-buf-offset nil left-page)
  1931.       (with-locked-page (disk-cache right-node t right-buf right-buf-offset nil right-page)
  1932.         (let ((left-used 0)
  1933.               (left-count 0)
  1934.               (right-used 0)
  1935.               (right-count 0))
  1936.           (declare (fixnum left-used left-count right-used right-count))
  1937.           (accessing-byte-array (left-buf left-buf-offset)
  1938.             (setq left-used (load.uw $btree_used)
  1939.                   left-count (load.uw $btree_count)))
  1940.           (accessing-byte-array (right-buf right-buf-offset)
  1941.             (setq right-used (load.uw $btree_used)
  1942.                   right-count (load.uw $btree_count)))
  1943.           (let* ((parent-ptr (+ parent-buf-offset parent-offset 4))
  1944.                  (parent-entry-size (accessing-byte-array (parent-buf)
  1945.                                       (normalize-size (+ 5 (load.b parent-ptr)) 4)))
  1946.                  (parent-string-size (- parent-entry-size 4))
  1947.                  (total-size (+ left-used parent-string-size right-used))
  1948.                  (space-available (+ left-used left-free)))
  1949.             (declare (fixnum parent-ptr parent-entry-size parent-string-size
  1950.                              total-size space-available))
  1951.             (if (<= total-size space-available)
  1952.               ; Can merge the two nodes
  1953.               (let ((left-ptr (+ left-buf-offset $btree_data left-used))
  1954.                     (right-ptr (+ right-buf-offset $btree_data)))
  1955.                 (declare (fixnum left-ptr))
  1956.                 (%copy-byte-array-portion
  1957.                  parent-buf parent-ptr parent-string-size
  1958.                  left-buf left-ptr left-page)
  1959.                 (incf parent-ptr parent-string-size)
  1960.                 (incf left-ptr parent-string-size)
  1961.                 (%copy-byte-array-portion
  1962.                  right-buf right-ptr right-used left-buf left-ptr)
  1963.                 (decf left-free (- total-size left-used))
  1964.                 (setq left-used total-size)
  1965.                 (incf left-count (1+ right-count))
  1966.                 (accessing-byte-array (left-buf left-buf-offset left-page)
  1967.                   (store.w left-used $btree_used)
  1968.                   (store.w left-free $btree_free)
  1969.                   (store.w left-count $btree_count))
  1970.                 (%btree-update-childrens-parents disk-cache left-node left-ptr)
  1971.                 (%btree-delete-from-node disk-cache btree parent-node parent-offset nil)
  1972.                 (dc-free-btree-node disk-cache btree right-node)
  1973.                 :merged)
  1974.               ; Can't merge, so balance as well as we can.
  1975.               (let* ((total-count (+ left-count right-count))
  1976.                      (sizes (make-array (1+ total-count)))
  1977.                      (new-left-used 4)
  1978.                      (new-parent-entry-size 0)
  1979.                      (new-right-used 0)
  1980.                      (left-used-diff 0)
  1981.                      (right-used-diff 0)
  1982.                      (bytes-to-copy 0)
  1983.                      (split-index 0)
  1984.                      (new-parent-string-size 0)
  1985.                      (new-parent-string (make-string 128))
  1986.                      child-update-node child-update-ptr child-update-end)
  1987.                 (declare (fixnum total-count new-left-used new-parent-entry-size
  1988.                                  new-right-used left-used-diff right-used-diff
  1989.                                  bytes-to-copy split-index new-parent-string-size)
  1990.                          (dynamic-extent sizes new-parent-string))
  1991.                 (%lookup-node-sizes disk-cache left-node sizes left-count)
  1992.                 (setf (svref sizes left-count) parent-entry-size)
  1993.                 (%lookup-node-sizes
  1994.                  disk-cache right-node sizes right-count nil nil (1+ left-count))
  1995.                 (setq new-parent-entry-size (svref sizes 0))
  1996.                 (dotimes (i total-count (error "Should have merged"))
  1997.                   (incf new-left-used new-parent-entry-size)
  1998.                   (setq new-parent-entry-size (svref sizes (the fixnum (1+ i))))
  1999.                   (when (>= new-left-used (- total-size new-left-used new-parent-entry-size))
  2000.                     (setq split-index i)
  2001.                     (return)))
  2002.                 (setq left-used-diff (- new-left-used left-used))
  2003.                 (unless (eql left-used-diff 0)
  2004.                   (setq new-parent-string-size (- new-parent-entry-size 4)
  2005.                         new-right-used (- total-size new-left-used new-parent-string-size)
  2006.                         right-used-diff (- right-used new-right-used))
  2007.                   (if (> left-used-diff 0)
  2008.                     (let* ((left-ptr (+ left-buf-offset $btree_data left-used))
  2009.                            (right-start-ptr (+ right-buf-offset $btree_data))
  2010.                            (right-ptr right-start-ptr))
  2011.                       (declare (fixnum left-ptr right-ptr))
  2012.                       (%copy-byte-array-portion
  2013.                        parent-buf parent-ptr parent-string-size left-buf left-ptr left-page)
  2014.                       (incf left-ptr parent-string-size)
  2015.                       (setq bytes-to-copy (- left-used-diff parent-string-size))
  2016.                       (%copy-byte-array-portion
  2017.                        right-buf right-ptr bytes-to-copy left-buf left-ptr left-page)
  2018.                       (setq child-update-node left-node
  2019.                             child-update-ptr left-ptr)
  2020.                       (incf right-ptr bytes-to-copy)
  2021.                       (%copy-byte-array-portion
  2022.                        right-buf right-ptr new-parent-string-size new-parent-string 0)
  2023.                       (incf right-ptr new-parent-string-size)
  2024.                       (%copy-byte-array-portion
  2025.                        right-buf right-ptr new-right-used
  2026.                        right-buf right-start-ptr right-page)
  2027.                       (incf right-start-ptr new-right-used)
  2028.                       (accessing-byte-array (right-buf nil right-page)
  2029.                         (fill.b right-start-ptr 0 right-used-diff)))
  2030.                     (let* ((left-diff-used (- left-used-diff))
  2031.                            (right-diff-used (- right-used-diff))
  2032.                            (left-start-ptr (+ left-buf-offset $btree_data new-left-used))
  2033.                            (left-ptr left-start-ptr)
  2034.                            (right-ptr (+ right-buf-offset $btree_data)))
  2035.                       (declare (fixnum left-diff-used right-diff-used
  2036.                                        left-start-ptr left-ptr right-ptr))
  2037.                       (%copy-byte-array-portion
  2038.                        left-buf left-ptr new-parent-string-size new-parent-string 0)
  2039.                       (incf left-ptr new-parent-string-size)
  2040.                       (setq bytes-to-copy (- left-diff-used new-parent-string-size))
  2041.                       (%copy-byte-array-portion
  2042.                        right-buf right-ptr right-used
  2043.                        right-buf (+ right-ptr right-diff-used) right-page)
  2044.                       (%copy-byte-array-portion
  2045.                        left-buf left-ptr bytes-to-copy right-buf right-ptr right-page)
  2046.                       (incf right-ptr bytes-to-copy)
  2047.                       (setq child-update-node right-node
  2048.                             child-update-end right-ptr)
  2049.                       (%copy-byte-array-portion
  2050.                        parent-buf parent-ptr parent-string-size
  2051.                        right-buf right-ptr right-page)
  2052.                       (accessing-byte-array (left-buf nil left-page)
  2053.                         (fill.b left-start-ptr 0 left-diff-used))))
  2054.                   (decf left-free left-used-diff)
  2055.                   (incf right-free right-used-diff)
  2056.                   (setq left-count (1+ split-index)
  2057.                         right-count (- total-count left-count))
  2058.                   (accessing-byte-array (left-buf left-buf-offset)
  2059.                     (store.w new-left-used $btree_used)
  2060.                     (store.w left-free $btree_free)
  2061.                     (store.w left-count $btree_count))
  2062.                   (accessing-byte-array (right-buf right-buf-offset)
  2063.                     (store.w new-right-used $btree_used)
  2064.                     (store.w right-free $btree_free)
  2065.                     (store.w right-count $btree_count))
  2066.                   (%btree-update-childrens-parents
  2067.                    disk-cache child-update-node child-update-ptr child-update-end)
  2068.                   (let* ((size-diff (- new-parent-string-size parent-string-size))
  2069.                          (parent-used 0)
  2070.                          (parent-free 0))
  2071.                     (declare (fixnum size-diff parent-free parent-used))
  2072.                     (accessing-byte-array (parent-buf parent-buf-offset)
  2073.                       (setq parent-used (load.uw $btree_used)
  2074.                             parent-free (load.uw $btree_free)))
  2075.                     (if (>= parent-free size-diff)
  2076.                       ; Modified parent-entry fits
  2077.                       (let ((new-parent-used (+ parent-used size-diff)))
  2078.                         (declare (fixnum parent-ptr new-parent-used))
  2079.                         (%copy-byte-array-portion
  2080.                          parent-buf (+ parent-ptr parent-string-size)
  2081.                          (- parent-used (- parent-offset $btree_data) parent-entry-size)
  2082.                          parent-buf (+ parent-ptr new-parent-string-size) parent-page)
  2083.                         (when (< size-diff 0)
  2084.                           (accessing-byte-array (parent-buf nil parent-page)
  2085.                             (fill.b (+ parent-buf-offset $btree_data new-parent-used)
  2086.                                     0 (- size-diff))))
  2087.                         (%copy-byte-array-portion
  2088.                          new-parent-string 0 new-parent-string-size
  2089.                          parent-buf parent-ptr parent-page)
  2090.                         (decf parent-free size-diff)
  2091.                         (accessing-byte-array (parent-buf parent-buf-offset)
  2092.                           (store.w new-parent-used $btree_used)
  2093.                           (store.w parent-free $btree_free)))
  2094.                       ; Modified parent-entry doesn't fit
  2095.                       (let ((new-parent-used (- parent-used parent-entry-size)))
  2096.                         (decf parent-ptr 4)         ; point at left-node pointer
  2097.                         (%copy-byte-array-portion
  2098.                          parent-buf (+ parent-ptr parent-entry-size)
  2099.                          (- parent-used (- parent-offset $btree_data) parent-entry-size)
  2100.                          parent-buf parent-ptr parent-page)
  2101.                         (incf parent-free parent-entry-size)
  2102.                         (accessing-byte-array (parent-buf parent-buf-offset parent-page)
  2103.                           (fill.b new-parent-used 0 parent-entry-size)
  2104.                           (store.w new-parent-used $btree_used)
  2105.                           (store.w parent-free $btree_free)
  2106.                           (store.w (1- (load.uw $btree_count)) $btree_count))
  2107.                         (let* ((key-length (accessing-byte-array (new-parent-string)
  2108.                                              (load.b 0))))
  2109.                           (declare (fixnum key-length))
  2110.                           (%copy-byte-array-portion
  2111.                            new-parent-string 1 key-length new-parent-string 0)
  2112.                           (%btree-insert-in-inner-node
  2113.                            disk-cache btree parent-node parent-offset
  2114.                            new-parent-string left-node nil key-length)))))
  2115.                   :balanced))))))))
  2116. ;  (check-btree-consistency disk-cache btree)
  2117.   )
  2118.  
  2119.  
  2120.  
  2121.  
  2122.  
  2123. ; Comment this out before release
  2124. (defun init-temp-btree ()
  2125.   (declare (special pheap dc b))
  2126.   (when (boundp 'pheap)
  2127.     (close-pheap pheap))
  2128.   (delete-file "temp.pheap")
  2129.   (create-pheap "temp.pheap")
  2130.   (setq pheap (open-pheap "temp.pheap")
  2131.         dc (pheap-disk-cache pheap))
  2132.   (dolist (w (windows :class 'inspector::inspector-window))
  2133.     (window-close w))
  2134.   (setq b (dc-make-btree dc))
  2135.   (let ((w (inspect dc)))
  2136.     (set-view-size w #@(413 384))
  2137.     (scroll-to-address (inspector::inspector-view w) (dc-%svref dc b $btree.root))))
  2138.  
  2139. (defvar *symbols* nil)
  2140. (defvar *value-offset* 0)
  2141.  
  2142. (defun *symbols* ()
  2143.   (let ((syms *symbols*))
  2144.     (unless syms
  2145.       (let ((hash (make-hash-table :test 'equal)))
  2146.         (do-symbols (s)
  2147.           (unless (gethash (symbol-name s) hash)
  2148.             (setf (gethash (symbol-name s) hash) t)
  2149.             (push s syms))))
  2150.       (setq *symbols* syms
  2151.             *value-offset* 0))
  2152.     syms))
  2153.  
  2154. (defun store-symbols (&optional (step-sym 0) check? (check-sym 0))
  2155.   (declare (special dc b))
  2156.   (let ((syms (*symbols*))
  2157.         (check-check-sym? nil)
  2158.         (i 0))
  2159.     (dolist (s syms)
  2160.       (let ((string (symbol-name s))
  2161.             (value (+ i *value-offset*)))
  2162.         (if (eq s step-sym)
  2163.           (step
  2164.            (dc-btree-store dc b string (require-type value 'fixnum) t))
  2165.           (dc-btree-store dc b string (require-type value 'fixnum) t))
  2166.         (when (eql s check-sym) (setq check-check-sym? i))
  2167.         (incf i)
  2168.         (when check-check-sym?
  2169.           (unless (eql check-check-sym? (dc-btree-lookup dc b (symbol-name check-sym)))
  2170.             (cerror "Continue" "Can't find ~s" check-sym)))
  2171.         (when (and check? (or (not (fixnump check?))
  2172.                               (eql 0 (mod i check?))))
  2173.           (format t "~&Checking ~d..." i)
  2174.           (check-symbols s)
  2175.           (terpri))))
  2176.     i))
  2177.  
  2178. (defun check-symbols (&optional (upto-and-including 0))
  2179.   (declare (special dc b))
  2180.   (let ((i 0))
  2181.     (dolist (s (*symbols*))
  2182.       (let ((was (dc-btree-lookup dc b (symbol-name s)))
  2183.             (value (+ i *value-offset*)))
  2184.         (unless (eql was value)
  2185.           (cerror "Continue"
  2186.                   "Sym: ~s, was: ~s, sb: ~s" s was value))
  2187.         (incf i)
  2188.         (when (eq s upto-and-including)
  2189.           (return))))
  2190.     i))
  2191.  
  2192. (defun delete-symbols (&optional (count nil) (check-period nil))
  2193.   (declare (special dc b))
  2194.   (let ((check-count (or check-period most-positive-fixnum)))
  2195.     (dotimes (i (or count (length *symbols*)))
  2196.       (when (null *symbols*) (return))
  2197.       (incf *value-offset*)
  2198.       (dc-btree-delete dc b (symbol-name (pop *symbols*)))
  2199.       (when (<= (decf check-count) 0)
  2200.         (setq check-count check-period)
  2201.         (format t "~&Checking ~d..." i)
  2202.         (check-symbols)
  2203.         (terpri)))))
  2204.  
  2205. (defun sort-syms-upto (sym)
  2206.   (let ((first-n (let ((res nil))
  2207.                    (dolist (s *symbols* (error "Not found"))
  2208.                      (push s res)
  2209.                      (when (eq s sym) (return res))))))
  2210.     (sort first-n #'string<)))
  2211.  
  2212. (defun btree-test (&optional (step-sym 0))
  2213.   (init-temp-btree)
  2214.   (store-symbols step-sym))
  2215.  
  2216. ; Checks consistency and returns how full the btree is.
  2217. (defun check-btree-consistency (disk-cache btree &optional check-nodes-and-count?)
  2218.   (let ((root (accessing-disk-cache (disk-cache)
  2219.                 (svref.p btree $btree.root))))
  2220.     (multiple-value-bind (free used nodes count)
  2221.                          (check-btree-node-consistency disk-cache root btree (%btree-leaf-node-p disk-cache root))
  2222.       (when check-nodes-and-count?
  2223.         (let ((missing-nodes (- (accessing-disk-cache (disk-cache)
  2224.                                   (svref.p btree $btree.nodes))
  2225.                                 nodes)))
  2226.           (unless (eql missing-nodes 0)
  2227.             (cerror "Continue" "~d. missing nodes" missing-nodes)))
  2228.         (let ((missing-entries (- (accessing-disk-cache (disk-cache)
  2229.                                     (svref.p btree $btree.count))
  2230.                                   count)))
  2231.           (unless (eql 0 missing-entries)
  2232.             (cerror "Continue" "~d. missing entries" missing-entries))))
  2233.       (values (/ used (float (+ free used)))
  2234.               nodes
  2235.               count))))
  2236.  
  2237. (defun check-btree-node-consistency (disk-cache node parent better-be-leaf-p)
  2238.   (require-satisfies dc-vector-subtype-p disk-cache node $v_btree-node)
  2239.   (accessing-disk-cache (disk-cache node)
  2240.     (let* ((free (load.uw $btree_free))
  2241.            (used (load.uw $btree_used))
  2242.            (count (load.uw $btree_count))
  2243.            (nodes 1)
  2244.            (sizes (make-array (1+ count)))
  2245.            (leaf? (%btree-leaf-node-p disk-cache node))
  2246.            (total-count (if leaf? count 0))
  2247.            (p $btree_data))
  2248.       (declare (fixnum free used count p)
  2249.                (dynamic-extent sizes))
  2250.       (unless (eq (not leaf?) (not better-be-leaf-p))
  2251.         (cerror "Continue."
  2252.                 "node: #x~x, parent: #x~x, better-be-leaf-p: ~s, leaf?: ~s"
  2253.                 node parent better-be-leaf-p leaf?))
  2254.       (unless (eql parent (load.l $btree_parent))
  2255.         (error "parent should be: #x~x, was: #x~x" parent (load.l $btree_parent)))
  2256.       (unless (eql 488 (+ free used))
  2257.         (cerror "Continue."
  2258.                 "~&(+ free used) is wrong. Node: #x~x, free: #x~x, used: #x~x~%"
  2259.                 node free used))
  2260.       (%lookup-node-sizes disk-cache node sizes count)
  2261.       (setf (aref sizes count) 0)
  2262.       (unless leaf?
  2263.         (let ((child-leaf-p (%btree-leaf-node-p disk-cache (load.l p))))
  2264.           (dotimes (i (1+ count))
  2265.             (multiple-value-bind (c-free c-used c-nodes c-count)
  2266.                                  (check-btree-node-consistency disk-cache (load.l p) node child-leaf-p)
  2267.               (incf free c-free)
  2268.               (incf used c-used)
  2269.               (incf nodes c-nodes)
  2270.               (incf total-count c-count))
  2271.             (incf p (aref sizes i)))))
  2272.       (values free used nodes total-count))))
  2273.              
  2274. #|
  2275. (advise %btree-insert-in-node
  2276.         (destructuring-bind (dc b node offset key-string value &optional value-imm? (key-length (length key-string))) arglist
  2277.           (declare (ignore offset value value-imm?))
  2278.           (if (or (%btree-leaf-node-p dc node)
  2279.                   (<= (normalize-size (+ 5 key-length))
  2280.                       (accessing-disk-cache (dc node) (load.uw $btree_free))))
  2281.             (:do-it)
  2282.             (step (:do-it))))
  2283.         :when :around)
  2284.  
  2285. (advise %balance-inner-node-after-deletion
  2286.         (step (:do-it))
  2287.         :when :around)
  2288. |#